From 551bb077aae3a96d2493b9a8b8e70b0070824598 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 5 May 2020 16:29:04 +0100 Subject: [PATCH 01/72] [Dashboard] Refresh container after clone panel is complete (#65252) --- .../public/application/embeddable/dashboard_container.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index 8346fd900caef..7e25d80c9d619 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -177,6 +177,7 @@ export class DashboardContainer extends Container Date: Tue, 5 May 2020 10:33:41 -0500 Subject: [PATCH 02/72] [Metrics UI] Require filterQuery to be ES JSON (#64937) --- .../components/expression.tsx | 2 +- .../infra/server/lib/alerting/common/utils.ts | 26 +++++++++++++++++++ ...r_inventory_metric_threshold_alert_type.ts | 16 +++++------- .../metric_threshold_executor.ts | 15 ++--------- .../register_metric_threshold_alert_type.ts | 13 +++++----- .../apis/infra/metrics_alerting.ts | 15 ----------- 6 files changed, 41 insertions(+), 46 deletions(-) create mode 100644 x-pack/plugins/infra/server/lib/alerting/common/utils.ts diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx index 5e14babddcb07..c1213b8ddfa1c 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx @@ -251,7 +251,7 @@ export const Expressions: React.FC = props => { context={alertsContext} derivedIndexPattern={derivedIndexPattern} source={source} - filterQuery={alertParams.filterQuery} + filterQuery={alertParams.filterQueryText} groupBy={alertParams.groupBy} /> diff --git a/x-pack/plugins/infra/server/lib/alerting/common/utils.ts b/x-pack/plugins/infra/server/lib/alerting/common/utils.ts new file mode 100644 index 0000000000000..a2c5b27c38fd6 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/common/utils.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { isEmpty } from 'lodash'; +import { schema } from '@kbn/config-schema'; + +export const oneOfLiterals = (arrayOfLiterals: Readonly) => + schema.string({ + validate: value => + arrayOfLiterals.includes(value) ? undefined : `must be one of ${arrayOfLiterals.join(' | ')}`, + }); + +export const validateIsStringElasticsearchJSONFilter = (value: string) => { + const errorMessage = 'filterQuery must be a valid Elasticsearch filter expressed in JSON'; + try { + const parsedValue = JSON.parse(value); + if (!isEmpty(parsedValue.bool)) { + return undefined; + } + return errorMessage; + } catch (e) { + return errorMessage; + } +}; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts index 3b6a1b5557bc6..71cde0175befe 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_alert_type.ts @@ -11,19 +11,13 @@ import { createInventoryMetricThresholdExecutor, FIRED_ACTIONS, } from './inventory_metric_threshold_executor'; -import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from './types'; +import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; +import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; const condition = schema.object({ threshold: schema.arrayOf(schema.number()), - comparator: schema.oneOf([ - schema.literal('>'), - schema.literal('<'), - schema.literal('>='), - schema.literal('<='), - schema.literal('between'), - schema.literal('outside'), - ]), + comparator: oneOfLiterals(Object.values(Comparator)), timeUnit: schema.string(), timeSize: schema.number(), metric: schema.string(), @@ -37,7 +31,9 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs { criteria: schema.arrayOf(condition), nodeType: schema.string(), - filterQuery: schema.maybe(schema.string()), + filterQuery: schema.maybe( + schema.string({ validate: validateIsStringElasticsearchJSONFilter }) + ), sourceId: schema.string(), }, { unknowns: 'allow' } diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index 5c34a058577a1..ec9389537835b 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -58,18 +58,7 @@ const getParsedFilterQuery: ( filterQuery: string | undefined ) => Record | Array> = filterQuery => { if (!filterQuery) return {}; - try { - return JSON.parse(filterQuery).bool; - } catch (e) { - return [ - { - query_string: { - query: filterQuery, - analyze_wildcard: true, - }, - }, - ]; - } + return JSON.parse(filterQuery).bool; }; export const getElasticsearchMetricQuery = ( @@ -265,8 +254,8 @@ export const createMetricThresholdExecutor = (libs: InfraBackendLibs, alertId: s const currentValues = await getMetric( services, criterion, - config.fields.timestamp, config.metricAlias, + config.fields.timestamp, groupBy, filterQuery ); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index 23611559a184f..e40cee1b9dda9 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -11,12 +11,7 @@ import { METRIC_EXPLORER_AGGREGATIONS } from '../../../../common/http_api/metric import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; import { METRIC_THRESHOLD_ALERT_TYPE_ID, Comparator } from './types'; import { InfraBackendLibs } from '../../infra_types'; - -const oneOfLiterals = (arrayOfLiterals: Readonly) => - schema.string({ - validate: value => - arrayOfLiterals.includes(value) ? undefined : `must be one of ${arrayOfLiterals.join(' | ')}`, - }); +import { oneOfLiterals, validateIsStringElasticsearchJSONFilter } from '../common/utils'; export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { const baseCriterion = { @@ -68,7 +63,11 @@ export function registerMetricThresholdAlertType(libs: InfraBackendLibs) { { criteria: schema.arrayOf(schema.oneOf([countCriterion, nonCountCriterion])), groupBy: schema.maybe(schema.string()), - filterQuery: schema.maybe(schema.string()), + filterQuery: schema.maybe( + schema.string({ + validate: validateIsStringElasticsearchJSONFilter, + }) + ), sourceId: schema.string(), alertOnNoData: schema.maybe(schema.boolean()), }, diff --git a/x-pack/test/api_integration/apis/infra/metrics_alerting.ts b/x-pack/test/api_integration/apis/infra/metrics_alerting.ts index 5c43e8938a8c1..b4ae29a2f3f85 100644 --- a/x-pack/test/api_integration/apis/infra/metrics_alerting.ts +++ b/x-pack/test/api_integration/apis/infra/metrics_alerting.ts @@ -57,21 +57,6 @@ export default function({ getService }: FtrProviderContext) { expect(result.hits).to.be.ok(); expect(result.aggregations).to.be.ok(); }); - it('should work with a filterQuery in KQL format', async () => { - const searchBody = getElasticsearchMetricQuery( - getSearchParams('avg'), - '@timestamp', - undefined, - '"agent.hostname":"foo"' - ); - const result = await client.search({ - index, - body: searchBody, - }); - expect(result.error).to.not.be.ok(); - expect(result.hits).to.be.ok(); - expect(result.aggregations).to.be.ok(); - }); }); describe('querying with a groupBy parameter', () => { for (const aggType of aggs) { From 6a6deef1515676aaa41cbcf6a4c78bc6d171c053 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 5 May 2020 11:36:40 -0400 Subject: [PATCH 03/72] Deprecate kibana user in favor of kibana_system user (#63186) --- config/kibana.yml | 2 +- docs/user/security/securing-kibana.asciidoc | 4 +- .../kbn-es/src/utils/native_realm.test.js | 16 +++--- src/cli/serve/serve.js | 2 +- .../elasticsearch_config.test.ts.snap | 2 +- .../elasticsearch_config.test.ts | 13 ++++- .../elasticsearch/elasticsearch_config.ts | 8 ++- x-pack/README.md | 2 +- x-pack/legacy/plugins/monitoring/README.md | 2 +- .../server/__tests__/deprecations.js | 10 +++- x-pack/plugins/monitoring/server/config.ts | 2 +- .../plugins/monitoring/server/deprecations.ts | 6 ++- x-pack/plugins/security/common/model/user.ts | 2 + .../users/edit_user/edit_user_page.test.tsx | 30 +++++++++++ .../users/edit_user/edit_user_page.tsx | 41 +++++++++----- .../management/users/user_utils.test.ts | 53 +++++++++++++++++++ .../public/management/users/user_utils.ts | 14 +++++ .../users/users_grid/users_grid_page.test.tsx | 32 +++++++++++ .../users/users_grid/users_grid_page.tsx | 15 ++++-- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - x-pack/test/functional/apps/security/users.js | 9 +++- .../functional/page_objects/security_page.js | 2 + 23 files changed, 229 insertions(+), 40 deletions(-) create mode 100644 x-pack/plugins/security/public/management/users/user_utils.test.ts diff --git a/config/kibana.yml b/config/kibana.yml index 0780841ca057e..8725888159506 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -40,7 +40,7 @@ # the username and password that the Kibana server uses to perform maintenance on the Kibana # index at startup. Your Kibana users still need to authenticate with Elasticsearch, which # is proxied through the Kibana server. -#elasticsearch.username: "kibana" +#elasticsearch.username: "kibana_system" #elasticsearch.password: "pass" # Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively. diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc index 24aacd6a47626..f4178bacb111e 100644 --- a/docs/user/security/securing-kibana.asciidoc +++ b/docs/user/security/securing-kibana.asciidoc @@ -31,14 +31,14 @@ file: [source,yaml] ----------------------------------------------- -elasticsearch.username: "kibana" +elasticsearch.username: "kibana_system" elasticsearch.password: "kibanapassword" ----------------------------------------------- The {kib} server submits requests as this user to access the cluster monitoring APIs and the `.kibana` index. The server does _not_ need access to user indices. -The password for the built-in `kibana` user is typically set as part of the +The password for the built-in `kibana_system` user is typically set as part of the {security} configuration process on {es}. For more information, see {ref}/built-in-users.html[Built-in users]. -- diff --git a/packages/kbn-es/src/utils/native_realm.test.js b/packages/kbn-es/src/utils/native_realm.test.js index 99c7ed1623014..54732f7136fcc 100644 --- a/packages/kbn-es/src/utils/native_realm.test.js +++ b/packages/kbn-es/src/utils/native_realm.test.js @@ -109,7 +109,7 @@ describe('setPasswords', () => { mockClient.security.getUser.mockImplementation(() => ({ body: { - kibana: { + kibana_system: { metadata: { _reserved: true, }, @@ -138,7 +138,7 @@ describe('setPasswords', () => { })); await nativeRealm.setPasswords({ - 'password.kibana': 'bar', + 'password.kibana_system': 'bar', }); expect(mockClient.security.changePassword.mock.calls).toMatchInlineSnapshot(` @@ -149,7 +149,7 @@ Array [ "password": "bar", }, "refresh": "wait_for", - "username": "kibana", + "username": "kibana_system", }, ], Array [ @@ -188,7 +188,7 @@ describe('getReservedUsers', () => { it('returns array of reserved usernames', async () => { mockClient.security.getUser.mockImplementation(() => ({ body: { - kibana: { + kibana_system: { metadata: { _reserved: true, }, @@ -206,17 +206,17 @@ describe('getReservedUsers', () => { }, })); - expect(await nativeRealm.getReservedUsers()).toEqual(['kibana', 'logstash_system']); + expect(await nativeRealm.getReservedUsers()).toEqual(['kibana_system', 'logstash_system']); }); }); describe('setPassword', () => { it('sets password for provided user', async () => { - await nativeRealm.setPassword('kibana', 'foo'); + await nativeRealm.setPassword('kibana_system', 'foo'); expect(mockClient.security.changePassword).toHaveBeenCalledWith({ body: { password: 'foo' }, refresh: 'wait_for', - username: 'kibana', + username: 'kibana_system', }); }); @@ -226,7 +226,7 @@ describe('setPassword', () => { }); await expect( - nativeRealm.setPassword('kibana', 'foo') + nativeRealm.setPassword('kibana_system', 'foo') ).rejects.toThrowErrorMatchingInlineSnapshot(`"SomeError"`); }); }); diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index 29d0fe16ee126..471939121143a 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -79,7 +79,7 @@ function applyConfigOverrides(rawConfig, opts, extraCliOptions) { set('optimize.watch', true); if (!has('elasticsearch.username')) { - set('elasticsearch.username', 'kibana'); + set('elasticsearch.username', 'kibana_system'); } if (!has('elasticsearch.password')) { diff --git a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap b/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap index e81336c8863f5..75627f311d9a5 100644 --- a/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap +++ b/src/core/server/elasticsearch/__snapshots__/elasticsearch_config.test.ts.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`#username throws if equal to "elastic", only while running from source 1`] = `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana\\" user instead."`; +exports[`#username throws if equal to "elastic", only while running from source 1`] = `"[username]: value of \\"elastic\\" is forbidden. This is a superuser account that can obfuscate privilege-related issues. You should use the \\"kibana_system\\" user instead."`; diff --git a/src/core/server/elasticsearch/elasticsearch_config.test.ts b/src/core/server/elasticsearch/elasticsearch_config.test.ts index de3f57298f461..cb4501a51e849 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.test.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.test.ts @@ -315,12 +315,21 @@ describe('deprecations', () => { const { messages } = applyElasticsearchDeprecations({ username: 'elastic' }); expect(messages).toMatchInlineSnapshot(` Array [ - "Setting [${CONFIG_PATH}.username] to \\"elastic\\" is deprecated. You should use the \\"kibana\\" user instead.", + "Setting [${CONFIG_PATH}.username] to \\"elastic\\" is deprecated. You should use the \\"kibana_system\\" user instead.", ] `); }); - it('does not log a warning if elasticsearch.username is set to something besides "elastic"', () => { + it('logs a warning if elasticsearch.username is set to "kibana"', () => { + const { messages } = applyElasticsearchDeprecations({ username: 'kibana' }); + expect(messages).toMatchInlineSnapshot(` + Array [ + "Setting [${CONFIG_PATH}.username] to \\"kibana\\" is deprecated. You should use the \\"kibana_system\\" user instead.", + ] + `); + }); + + it('does not log a warning if elasticsearch.username is set to something besides "elastic" or "kibana"', () => { const { messages } = applyElasticsearchDeprecations({ username: 'otheruser' }); expect(messages).toHaveLength(0); }); diff --git a/src/core/server/elasticsearch/elasticsearch_config.ts b/src/core/server/elasticsearch/elasticsearch_config.ts index d3012e361b3ed..c87c94bcd0b6a 100644 --- a/src/core/server/elasticsearch/elasticsearch_config.ts +++ b/src/core/server/elasticsearch/elasticsearch_config.ts @@ -55,7 +55,7 @@ export const configSchema = schema.object({ if (rawConfig === 'elastic') { return ( 'value of "elastic" is forbidden. This is a superuser account that can obfuscate ' + - 'privilege-related issues. You should use the "kibana" user instead.' + 'privilege-related issues. You should use the "kibana_system" user instead.' ); } }, @@ -131,7 +131,11 @@ const deprecations: ConfigDeprecationProvider = () => [ } if (es.username === 'elastic') { log( - `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana" user instead.` + `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.` + ); + } else if (es.username === 'kibana') { + log( + `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.` ); } if (es.ssl?.key !== undefined && es.ssl?.certificate === undefined) { diff --git a/x-pack/README.md b/x-pack/README.md index 42e54aa2f50f9..744d97ca02c75 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -12,7 +12,7 @@ Elasticsearch will run with a basic license. To run with a trial license, includ Example: `yarn es snapshot --license trial --password changeme` -By default, this will also set the password for native realm accounts to the password provided (`changeme` by default). This includes that of the `kibana` user which `elasticsearch.username` defaults to in development. If you wish to specific a password for a given native realm account, you can do that like so: `--password.kibana=notsecure` +By default, this will also set the password for native realm accounts to the password provided (`changeme` by default). This includes that of the `kibana_system` user which `elasticsearch.username` defaults to in development. If you wish to specify a password for a given native realm account, you can do that like so: `--password.kibana_system=notsecure` # Testing ## Running specific tests diff --git a/x-pack/legacy/plugins/monitoring/README.md b/x-pack/legacy/plugins/monitoring/README.md index e9ececa8c6350..0222f06e7ae91 100644 --- a/x-pack/legacy/plugins/monitoring/README.md +++ b/x-pack/legacy/plugins/monitoring/README.md @@ -74,7 +74,7 @@ cluster. % cat config/kibana.dev.yml monitoring.ui.elasticsearch: hosts: "http://localhost:9210" - username: "kibana" + username: "kibana_system" password: "changeme" ``` diff --git a/x-pack/plugins/monitoring/server/__tests__/deprecations.js b/x-pack/plugins/monitoring/server/__tests__/deprecations.js index aa8008346af85..5fc5debfa139e 100644 --- a/x-pack/plugins/monitoring/server/__tests__/deprecations.js +++ b/x-pack/plugins/monitoring/server/__tests__/deprecations.js @@ -92,7 +92,15 @@ describe('monitoring plugin deprecations', function() { expect(log.called).to.be(true); }); - it('does not log a warning if elasticsearch.username is set to something besides "elastic"', () => { + it('logs a warning if elasticsearch.username is set to "kibana"', () => { + const settings = { elasticsearch: { username: 'kibana' } }; + + const log = sinon.spy(); + transformDeprecations(settings, fromPath, log); + expect(log.called).to.be(true); + }); + + it('does not log a warning if elasticsearch.username is set to something besides "elastic" or "kibana"', () => { const settings = { elasticsearch: { username: 'otheruser' } }; const log = sinon.spy(); diff --git a/x-pack/plugins/monitoring/server/config.ts b/x-pack/plugins/monitoring/server/config.ts index 6e5092a112744..ad5bf95090186 100644 --- a/x-pack/plugins/monitoring/server/config.ts +++ b/x-pack/plugins/monitoring/server/config.ts @@ -119,7 +119,7 @@ export const configSchema = schema.object({ if (rawConfig === 'elastic') { return ( 'value of "elastic" is forbidden. This is a superuser account that can obfuscate ' + - 'privilege-related issues. You should use the "kibana" user instead.' + 'privilege-related issues. You should use the "kibana_system" user instead.' ); } }, diff --git a/x-pack/plugins/monitoring/server/deprecations.ts b/x-pack/plugins/monitoring/server/deprecations.ts index 3a3ec6ac799d2..d40837885e198 100644 --- a/x-pack/plugins/monitoring/server/deprecations.ts +++ b/x-pack/plugins/monitoring/server/deprecations.ts @@ -59,7 +59,11 @@ export const deprecations = ({ if (es) { if (es.username === 'elastic') { logger( - `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana" user instead.` + `Setting [${fromPath}.username] to "elastic" is deprecated. You should use the "kibana_system" user instead.` + ); + } else if (es.username === 'kibana') { + logger( + `Setting [${fromPath}.username] to "kibana" is deprecated. You should use the "kibana_system" user instead.` ); } } diff --git a/x-pack/plugins/security/common/model/user.ts b/x-pack/plugins/security/common/model/user.ts index e1bae2fc44e58..5c852e7a8f03d 100644 --- a/x-pack/plugins/security/common/model/user.ts +++ b/x-pack/plugins/security/common/model/user.ts @@ -12,6 +12,8 @@ export interface User { enabled: boolean; metadata?: { _reserved: boolean; + _deprecated?: boolean; + _deprecated_reason?: string; }; } diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx index be7517ff892b5..a97781ba25ea6 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.test.tsx @@ -32,6 +32,14 @@ const createUser = (username: string, roles = ['idk', 'something']) => { }; } + if (username === 'deprecated_user') { + user.metadata = { + _reserved: true, + _deprecated: true, + _deprecated_reason: 'beacuse I said so.', + }; + } + return user; }; @@ -162,6 +170,28 @@ describe('EditUserPage', () => { expectSaveButton(wrapper); }); + it('warns when viewing a depreciated user', async () => { + const user = createUser('deprecated_user'); + const { apiClient, rolesAPIClient } = buildClients(user); + const securitySetup = buildSecuritySetup(); + + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + expect(apiClient.getUser).toBeCalledTimes(1); + expect(securitySetup.authc.getCurrentUser).toBeCalledTimes(1); + + expect(findTestSubject(wrapper, 'deprecatedUserWarning')).toHaveLength(1); + }); + it('warns when user is assigned a deprecated role', async () => { const user = createUser('existing_user', ['deprecated-role']); const { apiClient, rolesAPIClient } = buildClients(user); diff --git a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx index 1c8130029bb50..7172ff178eb6b 100644 --- a/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx +++ b/x-pack/plugins/security/public/management/users/edit_user/edit_user_page.tsx @@ -38,6 +38,7 @@ import { RolesAPIClient } from '../../roles'; import { ConfirmDeleteUsers, ChangePasswordForm } from '../components'; import { UserValidator, UserValidationResult } from './validate_user'; import { RoleComboBox } from '../../role_combo_box'; +import { isUserDeprecated, getExtendedUserDeprecationNotice, isUserReserved } from '../user_utils'; import { UserAPIClient } from '..'; interface Props { @@ -244,7 +245,7 @@ export class EditUserPage extends Component { return ( - {user.username === 'kibana' ? ( + {user.username === 'kibana' || user.username === 'kibana_system' ? ( {

@@ -372,7 +373,7 @@ export class EditUserPage extends Component { isNewUser, showDeleteConfirmation, } = this.state; - const reserved = user.metadata && user.metadata._reserved; + const reserved = isUserReserved(user); if (!user || !roles) { return null; } @@ -427,15 +428,31 @@ export class EditUserPage extends Component { {reserved && ( - -

- +

+ -

-
+ /> +

+ + +
+ )} + + {isUserDeprecated(user) && ( + + + + )} {showDeleteConfirmation ? ( diff --git a/x-pack/plugins/security/public/management/users/user_utils.test.ts b/x-pack/plugins/security/public/management/users/user_utils.test.ts new file mode 100644 index 0000000000000..572b94ab08037 --- /dev/null +++ b/x-pack/plugins/security/public/management/users/user_utils.test.ts @@ -0,0 +1,53 @@ +/* + * 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 { User } from '../../../common/model'; +import { isUserReserved, isUserDeprecated, getExtendedUserDeprecationNotice } from './user_utils'; + +describe('#isUserReserved', () => { + it('returns false for a user with no metadata', () => { + expect(isUserReserved({} as User)).toEqual(false); + }); + + it('returns false for a user with the reserved flag set to false', () => { + expect(isUserReserved({ metadata: { _reserved: false } } as User)).toEqual(false); + }); + + it('returns true for a user with the reserved flag set to true', () => { + expect(isUserReserved({ metadata: { _reserved: true } } as User)).toEqual(true); + }); +}); + +describe('#isUserDeprecated', () => { + it('returns false for a user with no metadata', () => { + expect(isUserDeprecated({} as User)).toEqual(false); + }); + + it('returns false for a user with the deprecated flag set to false', () => { + expect(isUserDeprecated({ metadata: { _deprecated: false } } as User)).toEqual(false); + }); + + it('returns true for a user with the deprecated flag set to true', () => { + expect(isUserDeprecated({ metadata: { _deprecated: true } } as User)).toEqual(true); + }); +}); + +describe('#getExtendedUserDeprecationNotice', () => { + it('returns a notice when no reason is provided', () => { + expect( + getExtendedUserDeprecationNotice({ username: 'test_user' } as User) + ).toMatchInlineSnapshot(`"The test_user user is deprecated. "`); + }); + + it('returns a notice augmented with reason when provided', () => { + expect( + getExtendedUserDeprecationNotice({ + username: 'test_user', + metadata: { _reserved: true, _deprecated_reason: 'some reason' }, + } as User) + ).toMatchInlineSnapshot(`"The test_user user is deprecated. some reason"`); + }); +}); diff --git a/x-pack/plugins/security/public/management/users/user_utils.ts b/x-pack/plugins/security/public/management/users/user_utils.ts index f46f6f897e23b..211aad904d466 100644 --- a/x-pack/plugins/security/public/management/users/user_utils.ts +++ b/x-pack/plugins/security/public/management/users/user_utils.ts @@ -4,6 +4,20 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { User } from '../../../common/model'; export const isUserReserved = (user: User) => user.metadata?._reserved ?? false; + +export const isUserDeprecated = (user: User) => user.metadata?._deprecated ?? false; + +export const getExtendedUserDeprecationNotice = (user: User) => { + const reason = user.metadata?._deprecated_reason ?? ''; + return i18n.translate('xpack.security.management.users.extendedUserDeprecationNotice', { + defaultMessage: `The {username} user is deprecated. {reason}`, + values: { + username: user.username, + reason, + }, + }); +}; diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx index 031b67d5d9122..d3b85b83ff6a4 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.test.tsx @@ -102,6 +102,38 @@ describe('UsersGridPage', () => { expect(findTestSubject(wrapper, 'userDisabled')).toHaveLength(1); }); + it('renders deprecated users', async () => { + const apiClientMock = userAPIClientMock.create(); + apiClientMock.getUsers.mockImplementation(() => { + return Promise.resolve([ + { + username: 'foo', + email: 'foo@bar.net', + full_name: 'foo bar', + roles: ['kibana_user'], + enabled: true, + metadata: { + _reserved: true, + _deprecated: true, + _deprecated_reason: 'This user is not cool anymore.', + }, + }, + ]); + }); + + const wrapper = mountWithIntl( + + ); + + await waitForRender(wrapper); + + expect(findTestSubject(wrapper, 'userDeprecated')).toHaveLength(1); + }); + it('renders a warning when a user is assigned a deprecated role', async () => { const apiClientMock = userAPIClientMock.create(); apiClientMock.getUsers.mockImplementation(() => { diff --git a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx index 6837fcf430fe7..f8882129772f7 100644 --- a/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx +++ b/x-pack/plugins/security/public/management/users/users_grid/users_grid_page.tsx @@ -26,8 +26,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { NotificationsStart } from 'src/core/public'; import { User, Role } from '../../../../common/model'; import { ConfirmDeleteUsers } from '../components'; -import { isUserReserved } from '../user_utils'; -import { DisabledBadge, ReservedBadge } from '../../badges'; +import { isUserReserved, getExtendedUserDeprecationNotice, isUserDeprecated } from '../user_utils'; +import { DisabledBadge, ReservedBadge, DeprecatedBadge } from '../../badges'; import { RoleTableDisplay } from '../../role_table_display'; import { RolesAPIClient } from '../../roles'; import { UserAPIClient } from '..'; @@ -360,6 +360,7 @@ export class UsersGridPage extends Component { private getUserStatusBadges = (user: User) => { const enabled = user.enabled; const reserved = isUserReserved(user); + const deprecated = isUserDeprecated(user); const badges = []; if (!enabled) { @@ -378,9 +379,17 @@ export class UsersGridPage extends Component { /> ); } + if (deprecated) { + badges.push( + + ); + } return ( - + {badges.map((badge, index) => ( {badge} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 2367265862044..710642b03e329 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -12883,7 +12883,6 @@ "xpack.security.management.users.editUser.cancelButtonLabel": "キャンセル", "xpack.security.management.users.editUser.changePasswordButtonLabel": "パスワードを変更", "xpack.security.management.users.editUser.changePasswordExtraStepTitle": "追加ステップが必要です", - "xpack.security.management.users.editUser.changePasswordUpdateKibanaTitle": "Kibana ユーザーのパスワードを変更後、{kibana} ファイルを更新し Kibana を再起動する必要があります。", "xpack.security.management.users.editUser.changingUserNameAfterCreationDescription": "ユーザー名は作成後変更できません。", "xpack.security.management.users.editUser.confirmPasswordFormRowLabel": "パスワードの確認", "xpack.security.management.users.editUser.createUserButtonLabel": "ユーザーを作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ab7710b81d479..cf52ee6f3b515 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -12890,7 +12890,6 @@ "xpack.security.management.users.editUser.cancelButtonLabel": "取消", "xpack.security.management.users.editUser.changePasswordButtonLabel": "更改密码", "xpack.security.management.users.editUser.changePasswordExtraStepTitle": "需要额外的步骤", - "xpack.security.management.users.editUser.changePasswordUpdateKibanaTitle": "更改 Kibana 用户的密码后,必须更新 {kibana} 文件并重新启动 Kibana。", "xpack.security.management.users.editUser.changingUserNameAfterCreationDescription": "用户名一经创建,将无法更改。", "xpack.security.management.users.editUser.confirmPasswordFormRowLabel": "确认密码", "xpack.security.management.users.editUser.createUserButtonLabel": "创建用户", diff --git a/x-pack/test/functional/apps/security/users.js b/x-pack/test/functional/apps/security/users.js index 04d59334a01c4..bfc6950faecc6 100644 --- a/x-pack/test/functional/apps/security/users.js +++ b/x-pack/test/functional/apps/security/users.js @@ -18,15 +18,22 @@ export default function({ getService, getPageObjects }) { await PageObjects.security.clickElasticsearchUsers(); }); - it('should show the default elastic and kibana users', async function() { + it('should show the default elastic and kibana_system users', async function() { const users = indexBy(await PageObjects.security.getElasticsearchUsers(), 'username'); log.info('actualUsers = %j', users); log.info('config = %j', config.get('servers.elasticsearch.hostname')); if (config.get('servers.elasticsearch.hostname') === 'localhost') { expect(users.elastic.roles).to.eql(['superuser']); expect(users.elastic.reserved).to.be(true); + expect(users.elastic.deprecated).to.be(false); + + expect(users.kibana_system.roles).to.eql(['kibana_system']); + expect(users.kibana_system.reserved).to.be(true); + expect(users.kibana_system.deprecated).to.be(false); + expect(users.kibana.roles).to.eql(['kibana_system']); expect(users.kibana.reserved).to.be(true); + expect(users.kibana.deprecated).to.be(true); } else { expect(users.anonymous.roles).to.eql(['anonymous']); expect(users.anonymous.reserved).to.be(true); diff --git a/x-pack/test/functional/page_objects/security_page.js b/x-pack/test/functional/page_objects/security_page.js index 84eb0cc378771..08895de815b39 100644 --- a/x-pack/test/functional/page_objects/security_page.js +++ b/x-pack/test/functional/page_objects/security_page.js @@ -235,6 +235,7 @@ export function SecurityPageProvider({ getService, getPageObjects }) { const rolesElement = await user.findByTestSubject('userRowRoles'); // findAll is substantially faster than `find.descendantExistsByCssSelector for negative cases const isUserReserved = (await user.findAllByTestSubject('userReserved', 1)).length > 0; + const isUserDeprecated = (await user.findAllByTestSubject('userDeprecated', 1)).length > 0; return { username: await usernameElement.getVisibleText(), @@ -242,6 +243,7 @@ export function SecurityPageProvider({ getService, getPageObjects }) { email: await emailElement.getVisibleText(), roles: (await rolesElement.getVisibleText()).split('\n').map(role => role.trim()), reserved: isUserReserved, + deprecated: isUserDeprecated, }; }); } From f5d6466f89b1bdd5b112bb368635924b131ef2b6 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 5 May 2020 12:06:33 -0400 Subject: [PATCH 04/72] [Fleet] Fix display of local_metadata (#65260) --- .../components/agent_details.tsx | 19 ++++++++++++++++--- .../fleet/agent_details_page/index.tsx | 5 ++++- .../sections/fleet/agent_list_page/index.tsx | 18 ++++++++++++------ 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx index 12791b69d886c..6a1e6dc226903 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/components/agent_details.tsx @@ -30,7 +30,11 @@ export const AgentDetailsContent: React.FunctionComponent<{ title: i18n.translate('xpack.ingestManager.agentDetails.hostNameLabel', { defaultMessage: 'Host name', }), - description: agent.local_metadata['host.hostname'], + description: + typeof agent.local_metadata.host === 'object' && + typeof agent.local_metadata.host.hostname === 'string' + ? agent.local_metadata.host.hostname + : '-', }, { title: i18n.translate('xpack.ingestManager.agentDetails.hostIdLabel', { @@ -60,13 +64,22 @@ export const AgentDetailsContent: React.FunctionComponent<{ title: i18n.translate('xpack.ingestManager.agentDetails.versionLabel', { defaultMessage: 'Agent version', }), - description: agent.local_metadata['agent.version'], + description: + typeof agent.local_metadata.elastic === 'object' && + typeof agent.local_metadata.elastic.agent === 'object' && + typeof agent.local_metadata.elastic.agent.version === 'string' + ? agent.local_metadata.elastic.agent.version + : '-', }, { title: i18n.translate('xpack.ingestManager.agentDetails.platformLabel', { defaultMessage: 'Platform', }), - description: agent.local_metadata['os.platform'], + description: + typeof agent.local_metadata.os === 'object' && + typeof agent.local_metadata.os.platform === 'string' + ? agent.local_metadata.os.platform + : '-', }, ].map(({ title, description }) => { return ( diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx index e5d69dced7523..aa46f7cf976cd 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/agent_details_page/index.tsx @@ -75,7 +75,10 @@ export const AgentDetailsPage: React.FunctionComponent = () => {

- {agentData?.item?.local_metadata['host.hostname'] || ( + {typeof agentData?.item?.local_metadata?.host === 'object' && + typeof agentData?.item?.local_metadata?.host?.hostname === 'string' ? ( + agentData.item.local_metadata.host.hostname + ) : ( void; refre } ); +function safeMetadata(val: any) { + if (typeof val !== 'string') { + return '-'; + } + return val; +} + export const AgentListPage: React.FunctionComponent<{}> = () => { const defaultKuery: string = (useUrlParams().urlParams.kuery as string) || ''; const hasWriteCapabilites = useCapabilities().write; @@ -238,13 +245,13 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { const columns = [ { - field: 'local_metadata.host', + field: 'local_metadata.host.hostname', name: i18n.translate('xpack.ingestManager.agentList.hostColumnTitle', { defaultMessage: 'Host', }), render: (host: string, agent: Agent) => ( - {agent.local_metadata['host.hostname'] || host || ''} + {safeMetadata(host)} ), }, @@ -308,13 +315,12 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { }, }, { - field: 'local_metadata.version', + field: 'local_metadata.elastic.agent.version', width: '100px', name: i18n.translate('xpack.ingestManager.agentList.versionTitle', { defaultMessage: 'Version', }), - render: (version: string, agent: Agent) => - agent.local_metadata['agent.version'] || version || '', + render: (version: string, agent: Agent) => safeMetadata(version), }, { field: 'last_checkin', @@ -505,7 +511,7 @@ export const AgentListPage: React.FunctionComponent<{}> = () => { loading={isLoading && agentsRequest.isInitialRequest} hasActions={true} noItemsMessage={ - isLoading ? ( + isLoading && agentsRequest.isInitialRequest ? ( Date: Tue, 5 May 2020 19:08:25 +0300 Subject: [PATCH 05/72] [test/functional] page objects cleanup (#64891) * move point series functions to POs * remove unused monitoring_page Co-authored-by: Elastic Machine --- .../apps/visualize/_point_series_options.js | 24 +++--- test/functional/page_objects/index.ts | 6 -- .../page_objects/monitoring_page.js | 35 -------- .../page_objects/point_series_page.js | 81 ------------------- .../page_objects/visualize_chart_page.ts | 28 +++++++ .../page_objects/visualize_editor_page.ts | 31 ++++++- 6 files changed, 68 insertions(+), 137 deletions(-) delete mode 100644 test/functional/page_objects/monitoring_page.js delete mode 100644 test/functional/page_objects/point_series_page.js diff --git a/test/functional/apps/visualize/_point_series_options.js b/test/functional/apps/visualize/_point_series_options.js index d0f7810b6f8bb..17e0d1ca87fdd 100644 --- a/test/functional/apps/visualize/_point_series_options.js +++ b/test/functional/apps/visualize/_point_series_options.js @@ -27,12 +27,10 @@ export default function({ getService, getPageObjects }) { const PageObjects = getPageObjects([ 'visualize', 'header', - 'pointSeries', 'timePicker', 'visEditor', 'visChart', ]); - const pointSeriesVis = PageObjects.pointSeries; const inspector = getService('inspector'); async function initChart() { @@ -60,11 +58,11 @@ export default function({ getService, getPageObjects }) { await PageObjects.visEditor.clickMetricsAndAxes(); // add another value axis log.debug('adding axis'); - await pointSeriesVis.clickAddAxis(); + await PageObjects.visEditor.clickAddAxis(); // set average count to use second value axis await PageObjects.visEditor.toggleAccordion('visEditorSeriesAccordion3'); log.debug('Average memory value axis - ValueAxis-2'); - await pointSeriesVis.setSeriesAxis(1, 'ValueAxis-2'); + await PageObjects.visEditor.setSeriesAxis(1, 'ValueAxis-2'); await PageObjects.visChart.waitForVisualizationRenderingStabilized(); await PageObjects.visEditor.clickGo(); } @@ -151,16 +149,16 @@ export default function({ getService, getPageObjects }) { }); it('should put secondary axis on the right', async function() { - const length = await pointSeriesVis.getRightValueAxes(); + const length = await PageObjects.visChart.getRightValueAxes(); expect(length).to.be(1); }); }); describe('multiple chart types', function() { it('should change average series type to histogram', async function() { - await pointSeriesVis.setSeriesType(1, 'histogram'); + await PageObjects.visEditor.setSeriesType(1, 'histogram'); await PageObjects.visEditor.clickGo(); - const length = await pointSeriesVis.getHistogramSeries(); + const length = await PageObjects.visChart.getHistogramSeries(); expect(length).to.be(1); }); }); @@ -171,9 +169,9 @@ export default function({ getService, getPageObjects }) { }); it('should show category grid lines', async function() { - await pointSeriesVis.toggleGridCategoryLines(); + await PageObjects.visEditor.toggleGridCategoryLines(); await PageObjects.visEditor.clickGo(); - const gridLines = await pointSeriesVis.getGridLines(); + const gridLines = await PageObjects.visChart.getGridLines(); expect(gridLines.length).to.be(9); gridLines.forEach(gridLine => { expect(gridLine.y).to.be(0); @@ -181,10 +179,10 @@ export default function({ getService, getPageObjects }) { }); it('should show value axis grid lines', async function() { - await pointSeriesVis.setGridValueAxis('ValueAxis-2'); - await pointSeriesVis.toggleGridCategoryLines(); + await PageObjects.visEditor.setGridValueAxis('ValueAxis-2'); + await PageObjects.visEditor.toggleGridCategoryLines(); await PageObjects.visEditor.clickGo(); - const gridLines = await pointSeriesVis.getGridLines(); + const gridLines = await PageObjects.visChart.getGridLines(); expect(gridLines.length).to.be(9); gridLines.forEach(gridLine => { expect(gridLine.x).to.be(0); @@ -212,7 +210,7 @@ export default function({ getService, getPageObjects }) { }); it('should render a custom axis title when one is set, overriding the custom label', async function() { - await pointSeriesVis.setAxisTitle(axisTitle); + await PageObjects.visEditor.setAxisTitle(axisTitle); await PageObjects.visEditor.clickGo(); const title = await PageObjects.visChart.getYAxisTitle(); expect(title).to.be(axisTitle); diff --git a/test/functional/page_objects/index.ts b/test/functional/page_objects/index.ts index 4077036cbe793..01301109b80ef 100644 --- a/test/functional/page_objects/index.ts +++ b/test/functional/page_objects/index.ts @@ -25,11 +25,7 @@ import { DiscoverPageProvider } from './discover_page'; import { ErrorPageProvider } from './error_page'; import { HeaderPageProvider } from './header_page'; import { HomePageProvider } from './home_page'; -// @ts-ignore not TS yet -import { MonitoringPageProvider } from './monitoring_page'; import { NewsfeedPageProvider } from './newsfeed_page'; -// @ts-ignore not TS yet -import { PointSeriesPageProvider } from './point_series_page'; import { SettingsPageProvider } from './settings_page'; import { SharePageProvider } from './share_page'; import { ShieldPageProvider } from './shield_page'; @@ -52,9 +48,7 @@ export const pageObjects = { error: ErrorPageProvider, header: HeaderPageProvider, home: HomePageProvider, - monitoring: MonitoringPageProvider, newsfeed: NewsfeedPageProvider, - pointSeries: PointSeriesPageProvider, settings: SettingsPageProvider, share: SharePageProvider, shield: ShieldPageProvider, diff --git a/test/functional/page_objects/monitoring_page.js b/test/functional/page_objects/monitoring_page.js deleted file mode 100644 index 7dab9dc3e52b1..0000000000000 --- a/test/functional/page_objects/monitoring_page.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 function MonitoringPageProvider({ getService }) { - const find = getService('find'); - - class MonitoringPage { - async getWelcome() { - const el = await find.displayedByCssSelector('render-directive'); - return await el.getVisibleText(); - } - - async clickOptOut() { - return find.clickByLinkText('Opt out here'); - } - } - - return new MonitoringPage(); -} diff --git a/test/functional/page_objects/point_series_page.js b/test/functional/page_objects/point_series_page.js deleted file mode 100644 index 594facb8b74b5..0000000000000 --- a/test/functional/page_objects/point_series_page.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 function PointSeriesPageProvider({ getService }) { - const testSubjects = getService('testSubjects'); - const log = getService('log'); - const find = getService('find'); - - class PointSeriesVis { - async clickAddAxis() { - return await testSubjects.click('visualizeAddYAxisButton'); - } - - async setAxisTitle(title, { index = 0 } = {}) { - return await testSubjects.setValue(`valueAxisTitle${index}`, title); - } - - async getRightValueAxes() { - const axes = await find.allByCssSelector('.visAxis__column--right g.axis'); - return axes.length; - } - - async getHistogramSeries() { - const series = await find.allByCssSelector('.series.histogram'); - return series.length; - } - - async getGridLines() { - const grid = await find.byCssSelector('g.grid'); - const $ = await grid.parseDomContent(); - return $('path') - .toArray() - .map(line => { - const dAttribute = $(line).attr('d'); - const firstPoint = dAttribute - .split('L')[0] - .replace('M', '') - .split(','); - return { - x: parseFloat(firstPoint[0]), - y: parseFloat(firstPoint[1]), - }; - }); - } - - async toggleGridCategoryLines() { - return await testSubjects.click('showCategoryLines'); - } - - async setGridValueAxis(axis) { - log.debug(`setGridValueAxis(${axis})`); - await find.selectValue('select#gridAxis', axis); - } - - async setSeriesAxis(series, axis) { - await find.selectValue(`select#seriesValueAxis${series}`, axis); - } - - async setSeriesType(series, type) { - await find.selectValue(`select#seriesType${series}`, type); - } - } - - return new PointSeriesVis(); -} diff --git a/test/functional/page_objects/visualize_chart_page.ts b/test/functional/page_objects/visualize_chart_page.ts index 0f14489a39dbc..71e722a9c8fdd 100644 --- a/test/functional/page_objects/visualize_chart_page.ts +++ b/test/functional/page_objects/visualize_chart_page.ts @@ -379,6 +379,34 @@ export function VisualizeChartPageProvider({ getService, getPageObjects }: FtrPr ); return values.filter(item => item.length > 0); } + + public async getRightValueAxes() { + const axes = await find.allByCssSelector('.visAxis__column--right g.axis'); + return axes.length; + } + + public async getHistogramSeries() { + const series = await find.allByCssSelector('.series.histogram'); + return series.length; + } + + public async getGridLines(): Promise> { + const grid = await find.byCssSelector('g.grid'); + const $ = await grid.parseDomContent(); + return $('path') + .toArray() + .map(line => { + const dAttribute = $(line).attr('d'); + const firstPoint = dAttribute + .split('L')[0] + .replace('M', '') + .split(','); + return { + x: parseFloat(firstPoint[0]), + y: parseFloat(firstPoint[1]), + }; + }); + } } return new VisualizeChart(); diff --git a/test/functional/page_objects/visualize_editor_page.ts b/test/functional/page_objects/visualize_editor_page.ts index 41c12170cf4dc..8b0ec3ba26028 100644 --- a/test/functional/page_objects/visualize_editor_page.ts +++ b/test/functional/page_objects/visualize_editor_page.ts @@ -453,8 +453,8 @@ export function VisualizeEditorPageProvider({ getService, getPageObjects }: FtrP return await comboBox.getComboBoxSelectedOptions('visEditorInterval'); } - public async getNumericInterval(agg = 2) { - return await testSubjects.getAttribute(`visEditorInterval${agg}`, 'value'); + public async getNumericInterval(aggNth = 2) { + return await testSubjects.getAttribute(`visEditorInterval${aggNth}`, 'value'); } public async clickMetricEditor() { @@ -487,6 +487,33 @@ export function VisualizeEditorPageProvider({ getService, getPageObjects }: FtrP } await options[optionIndex].click(); } + + // point series + + async clickAddAxis() { + return await testSubjects.click('visualizeAddYAxisButton'); + } + + async setAxisTitle(title: string, aggNth = 0) { + return await testSubjects.setValue(`valueAxisTitle${aggNth}`, title); + } + + public async toggleGridCategoryLines() { + return await testSubjects.click('showCategoryLines'); + } + + public async setGridValueAxis(axis: string) { + log.debug(`setGridValueAxis(${axis})`); + await find.selectValue('select#gridAxis', axis); + } + + public async setSeriesAxis(seriesNth: number, axis: string) { + await find.selectValue(`select#seriesValueAxis${seriesNth}`, axis); + } + + public async setSeriesType(seriesNth: number, type: string) { + await find.selectValue(`select#seriesType${seriesNth}`, type); + } } return new VisualizeEditorPage(); From 9a0b7dde516a058bf2be2d1743f6cf1aafbaca90 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 5 May 2020 12:17:37 -0400 Subject: [PATCH 06/72] [Fleet] Redirect user to fleet setup in enrollment flyout (#65265) --- .../agent_enrollment_flyout/index.tsx | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx index 002b4772d9216..ff7c2f705e7b7 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/components/agent_enrollment_flyout/index.tsx @@ -23,8 +23,10 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { AgentConfig } from '../../../../types'; import { EnrollmentStepAgentConfig } from './config_selection'; -import { useGetOneEnrollmentAPIKey, useCore, useGetSettings } from '../../../../hooks'; +import { useGetOneEnrollmentAPIKey, useCore, useGetSettings, useLink } from '../../../../hooks'; import { ManualInstructions } from '../../../../components/enrollment_instructions'; +import { FLEET_PATH } from '../../../../constants'; +import { useFleetStatus } from '../../../../hooks/use_fleet_status'; interface Props { onClose: () => void; @@ -36,6 +38,9 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ agentConfigs = [], }) => { const core = useCore(); + const fleetStatus = useFleetStatus(); + const fleetLink = useLink(FLEET_PATH); + const [selectedAPIKeyId, setSelectedAPIKeyId] = useState(); const settings = useGetSettings(); @@ -104,7 +109,28 @@ export const AgentEnrollmentFlyout: React.FunctionComponent = ({ - + {fleetStatus.isReady ? ( + <> + + + ) : ( + <> + + + + ), + }} + /> + + )} From e02350cdc7d3e6071b262bc73ba2a3a6187fd96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 5 May 2020 18:22:47 +0200 Subject: [PATCH 07/72] [APM] Update path to APM app after move to NP (#65034) --- .ci/end2end.groovy | 4 ++-- .eslintignore | 2 +- .eslintrc.js | 8 ++++---- .github/CODEOWNERS | 2 +- .github/paths-labeller.yml | 2 +- .gitignore | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.ci/end2end.groovy b/.ci/end2end.groovy index 8ad810717d86e..8e9b041d32d3e 100644 --- a/.ci/end2end.groovy +++ b/.ci/end2end.groovy @@ -13,7 +13,7 @@ pipeline { BASE_DIR = 'src/github.com/elastic/kibana' HOME = "${env.WORKSPACE}" APM_ITS = 'apm-integration-testing' - CYPRESS_DIR = 'x-pack/legacy/plugins/apm/e2e' + CYPRESS_DIR = 'x-pack/plugins/apm/e2e' PIPELINE_LOG_LEVEL = 'DEBUG' } options { @@ -39,7 +39,7 @@ pipeline { shallow: false, reference: "/var/lib/jenkins/.git-references/kibana.git") script { dir("${BASE_DIR}"){ - def regexps =[ "^x-pack/legacy/plugins/apm/.*" ] + def regexps =[ "^x-pack/plugins/apm/.*" ] env.APM_UPDATED = isGitRegionMatch(patterns: regexps) } } diff --git a/.eslintignore b/.eslintignore index 4913192e81c1d..53b3d80720439 100644 --- a/.eslintignore +++ b/.eslintignore @@ -25,7 +25,7 @@ target /src/plugins/vis_type_timelion/public/_generated_/** /src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.* /x-pack/legacy/plugins/**/__tests__/fixtures/** -/x-pack/legacy/plugins/apm/e2e/cypress/**/snapshots.js +/x-pack/plugins/apm/e2e/cypress/**/snapshots.js /x-pack/legacy/plugins/canvas/canvas_plugin /x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts /x-pack/legacy/plugins/canvas/shareable_runtime/build diff --git a/.eslintrc.js b/.eslintrc.js index 8b33ec83347a8..1f42ff48b4dc9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -306,7 +306,7 @@ module.exports = { { files: [ 'x-pack/test/functional/apps/**/*.js', - 'x-pack/legacy/plugins/apm/**/*.js', + 'x-pack/plugins/apm/**/*.js', 'test/*/config.ts', 'test/*/config_open.ts', 'test/*/{tests,test_suites,apis,apps}/**/*', @@ -393,7 +393,7 @@ module.exports = { 'x-pack/**/*.test.js', 'x-pack/test_utils/**/*', 'x-pack/gulpfile.js', - 'x-pack/legacy/plugins/apm/public/utils/testHelpers.js', + 'x-pack/plugins/apm/public/utils/testHelpers.js', ], rules: { 'import/no-extraneous-dependencies': [ @@ -519,7 +519,7 @@ module.exports = { * APM overrides */ { - files: ['x-pack/legacy/plugins/apm/**/*.js'], + files: ['x-pack/plugins/apm/**/*.js'], rules: { 'no-unused-vars': ['error', { ignoreRestSiblings: true }], 'no-console': ['warn', { allow: ['error'] }], @@ -527,7 +527,7 @@ module.exports = { }, { plugins: ['react-hooks'], - files: ['x-pack/legacy/plugins/apm/**/*.{ts,tsx}'], + files: ['x-pack/plugins/apm/**/*.{ts,tsx}'], rules: { 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 'react-hooks/exhaustive-deps': ['error', { additionalHooks: '^useFetcher$' }], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6e616cf78c206..280cb6fbd1b1d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -66,7 +66,7 @@ /x-pack/plugins/drilldowns/ @elastic/kibana-app-arch # APM -/x-pack/legacy/plugins/apm/ @elastic/apm-ui +/x-pack/plugins/apm/ @elastic/apm-ui /x-pack/plugins/apm/ @elastic/apm-ui /x-pack/test/functional/apps/apm/ @elastic/apm-ui /src/legacy/core_plugins/apm_oss/ @elastic/apm-ui diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 89e0af270c54d..efdb041e2b37a 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -10,7 +10,7 @@ - "src/plugins/bfetch/**/*.*" - "Team:apm" - "x-pack/plugins/apm/**/*.*" - - "x-pack/legacy/plugins/apm/**/*.*" + - "x-pack/plugins/apm/**/*.*" - "Team:uptime": - "x-pack/plugins/uptime/**/*.*" - "x-pack/legacy/plugins/uptime/**/*.*" diff --git a/.gitignore b/.gitignore index bd7a954f950e9..13c7cd5fb2769 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,6 @@ package-lock.json *.sublime-* npm-debug.log* .tern-project -x-pack/legacy/plugins/apm/tsconfig.json +x-pack/plugins/apm/tsconfig.json apm.tsconfig.json -/x-pack/legacy/plugins/apm/e2e/snapshots.js +/x-pack/plugins/apm/e2e/snapshots.js From f26292e0a2c589909ba09ecfee61d33f76f14bae Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 5 May 2020 09:29:48 -0700 Subject: [PATCH 08/72] Revert "[SIEM] Adds 'Configure connector' Cypress test (#64807)" (#65297) This reverts commit 5c2fb4ce386ccba823d6b2b7e834ff9443c180e2. --- .../integration/cases_connectors.spec.ts | 47 ----------------- x-pack/plugins/siem/cypress/objects/case.ts | 14 ----- .../plugins/siem/cypress/screens/all_cases.ts | 2 - .../siem/cypress/screens/configure_cases.ts | 30 ----------- .../plugins/siem/cypress/tasks/all_cases.ts | 10 +--- .../siem/cypress/tasks/configure_cases.ts | 52 ------------------- 6 files changed, 1 insertion(+), 154 deletions(-) delete mode 100644 x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts delete mode 100644 x-pack/plugins/siem/cypress/screens/configure_cases.ts delete mode 100644 x-pack/plugins/siem/cypress/tasks/configure_cases.ts diff --git a/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts b/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts deleted file mode 100644 index 2d650b1bbd9d1..0000000000000 --- a/x-pack/plugins/siem/cypress/integration/cases_connectors.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { serviceNowConnector } from '../objects/case'; - -import { TOASTER } from '../screens/configure_cases'; - -import { goToEditExternalConnection } from '../tasks/all_cases'; -import { - addServiceNowConnector, - openAddNewConnectorOption, - saveChanges, - selectLastConnectorCreated, -} from '../tasks/configure_cases'; -import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; - -import { CASES } from '../urls/navigation'; - -describe('Cases connectors', () => { - before(() => { - cy.server(); - cy.route('POST', '**/api/action').as('createConnector'); - cy.route('POST', '**/api/cases/configure').as('saveConnector'); - }); - - it('Configures a new connector', () => { - loginAndWaitForPageWithoutDateRange(CASES); - goToEditExternalConnection(); - openAddNewConnectorOption(); - addServiceNowConnector(serviceNowConnector); - - cy.wait('@createConnector') - .its('status') - .should('eql', 200); - cy.get(TOASTER).should('have.text', "Created 'New connector'"); - - selectLastConnectorCreated(); - saveChanges(); - - cy.wait('@saveConnector', { timeout: 10000 }) - .its('status') - .should('eql', 200); - cy.get(TOASTER).should('have.text', 'Saved external connection settings'); - }); -}); diff --git a/x-pack/plugins/siem/cypress/objects/case.ts b/x-pack/plugins/siem/cypress/objects/case.ts index 12d3f925169af..1c7bc34bca417 100644 --- a/x-pack/plugins/siem/cypress/objects/case.ts +++ b/x-pack/plugins/siem/cypress/objects/case.ts @@ -14,13 +14,6 @@ export interface TestCase { reporter: string; } -export interface Connector { - connectorName: string; - URL: string; - username: string; - password: string; -} - const caseTimeline: Timeline = { title: 'SIEM test', description: 'description', @@ -34,10 +27,3 @@ export const case1: TestCase = { timeline: caseTimeline, reporter: 'elastic', }; - -export const serviceNowConnector: Connector = { - connectorName: 'New connector', - URL: 'https://www.test.service-now.com', - username: 'Username Name', - password: 'password', -}; diff --git a/x-pack/plugins/siem/cypress/screens/all_cases.ts b/x-pack/plugins/siem/cypress/screens/all_cases.ts index 4fa6b69eea7c3..b1e4c66515352 100644 --- a/x-pack/plugins/siem/cypress/screens/all_cases.ts +++ b/x-pack/plugins/siem/cypress/screens/all_cases.ts @@ -39,5 +39,3 @@ export const ALL_CASES_TAGS = (index: number) => { }; export const ALL_CASES_TAGS_COUNT = '[data-test-subj="options-filter-popover-button-Tags"]'; - -export const EDIT_EXTERNAL_CONNECTION = '[data-test-subj="configure-case-button"]'; diff --git a/x-pack/plugins/siem/cypress/screens/configure_cases.ts b/x-pack/plugins/siem/cypress/screens/configure_cases.ts deleted file mode 100644 index 5a1e897c43e27..0000000000000 --- a/x-pack/plugins/siem/cypress/screens/configure_cases.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export const ADD_NEW_CONNECTOR_OPTION_LINK = - '[data-test-subj="case-configure-add-connector-button"]'; - -export const CONNECTOR = (id: string) => { - return `[data-test-subj='dropdown-connector-${id}']`; -}; - -export const CONNECTOR_NAME = '[data-test-subj="nameInput"]'; - -export const CONNECTORS_DROPDOWN = '[data-test-subj="dropdown-connectors"]'; - -export const PASSWORD = '[data-test-subj="connector-servicenow-password-form-input"]'; - -export const SAVE_BTN = '[data-test-subj="saveNewActionButton"]'; - -export const SAVE_CHANGES_BTN = '[data-test-subj="case-configure-action-bottom-bar-save-button"]'; - -export const SERVICE_NOW_CONNECTOR_CARD = '[data-test-subj=".servicenow-card"]'; - -export const TOASTER = '[data-test-subj="euiToastHeader"]'; - -export const URL = '[data-test-subj="apiUrlFromInput"]'; - -export const USERNAME = '[data-test-subj="connector-servicenow-username-form-input"]'; diff --git a/x-pack/plugins/siem/cypress/tasks/all_cases.ts b/x-pack/plugins/siem/cypress/tasks/all_cases.ts index 8ebe35e173e59..f374532201324 100644 --- a/x-pack/plugins/siem/cypress/tasks/all_cases.ts +++ b/x-pack/plugins/siem/cypress/tasks/all_cases.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - ALL_CASES_NAME, - ALL_CASES_CREATE_NEW_CASE_BTN, - EDIT_EXTERNAL_CONNECTION, -} from '../screens/all_cases'; +import { ALL_CASES_NAME, ALL_CASES_CREATE_NEW_CASE_BTN } from '../screens/all_cases'; export const goToCreateNewCase = () => { cy.get(ALL_CASES_CREATE_NEW_CASE_BTN).click({ force: true }); @@ -17,7 +13,3 @@ export const goToCreateNewCase = () => { export const goToCaseDetails = () => { cy.get(ALL_CASES_NAME).click({ force: true }); }; - -export const goToEditExternalConnection = () => { - cy.get(EDIT_EXTERNAL_CONNECTION).click({ force: true }); -}; diff --git a/x-pack/plugins/siem/cypress/tasks/configure_cases.ts b/x-pack/plugins/siem/cypress/tasks/configure_cases.ts deleted file mode 100644 index 9172e02708ae7..0000000000000 --- a/x-pack/plugins/siem/cypress/tasks/configure_cases.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - ADD_NEW_CONNECTOR_OPTION_LINK, - CONNECTOR, - CONNECTOR_NAME, - CONNECTORS_DROPDOWN, - PASSWORD, - SAVE_BTN, - SAVE_CHANGES_BTN, - SERVICE_NOW_CONNECTOR_CARD, - URL, - USERNAME, -} from '../screens/configure_cases'; -import { MAIN_PAGE } from '../screens/siem_main'; - -import { Connector } from '../objects/case'; - -export const addServiceNowConnector = (connector: Connector) => { - cy.get(SERVICE_NOW_CONNECTOR_CARD).click(); - cy.get(CONNECTOR_NAME).type(connector.connectorName); - cy.get(URL).type(connector.URL); - cy.get(USERNAME).type(connector.username); - cy.get(PASSWORD).type(connector.password); - cy.get(SAVE_BTN).click({ force: true }); -}; - -export const openAddNewConnectorOption = () => { - cy.get(MAIN_PAGE).then($page => { - if ($page.find(SERVICE_NOW_CONNECTOR_CARD).length !== 1) { - cy.wait(1000); - cy.get(ADD_NEW_CONNECTOR_OPTION_LINK).click({ force: true }); - } - }); -}; - -export const saveChanges = () => { - cy.get(SAVE_CHANGES_BTN).click(); -}; - -export const selectLastConnectorCreated = () => { - cy.get(CONNECTORS_DROPDOWN).click({ force: true }); - cy.get('@createConnector') - .its('response') - .then(response => { - cy.get(CONNECTOR(response.body.id)).click(); - }); -}; From df1874756fb403ae2343330f80564411d9460679 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 5 May 2020 09:33:09 -0700 Subject: [PATCH 09/72] Disallows commonjs in new platform public (#65218) Signed-off-by: Tyler Smalley --- .eslintrc.js | 10 + .../editor/legacy/console_editor/editor.tsx | 6 +- .../application/containers/settings.tsx | 8 +- .../use_send_current_request_to_es.ts | 4 +- .../__tests__/output_tokenization.test.js | 2 +- .../models/legacy_core_editor/mode/input.js | 7 +- .../mode/input_highlight_rules.js | 2 +- .../models/legacy_core_editor/mode/output.js | 6 +- .../mode/output_highlight_rules.js | 2 +- .../legacy_core_editor/theme_sense_dark.js | 2 +- .../__tests__/integration.test.js | 6 +- .../__tests__/sense_editor.test.js | 2 +- .../__jest__/url_autocomplete.test.js | 2 +- .../autocomplete/__jest__/url_params.test.js | 2 +- .../public/lib/autocomplete/body_completer.js | 2 +- .../field_autocomplete_component.js | 4 +- .../index_autocomplete_component.js | 4 +- .../template_autocomplete_component.js | 4 +- .../components/type_autocomplete_component.js | 4 +- .../username_autocomplete_component.js | 4 +- .../console/public/lib/autocomplete/engine.js | 2 +- .../public/lib/autocomplete/url_params.js | 2 +- .../__tests__/curl_parsing.test.js | 10 +- .../public/lib/kb/__tests__/kb.test.js | 4 +- src/plugins/console/public/lib/kb/api.js | 2 +- .../lib/mappings/__tests__/mapping.test.js | 2 +- .../console/public/lib/mappings/mappings.js | 39 +- .../public/lib/utils/__tests__/utils.test.js | 2 +- .../fixtures/follower_index.ts | 2 +- .../util/geo_json_clean_and_validate.test.js | 2 +- .../file_upload/public/util/pattern_reader.js | 2 +- .../public/angular/graph_client_workspace.js | 2739 ++++++++--------- .../angular/graph_client_workspace.test.js | 4 +- x-pack/plugins/graph/public/app.js | 4 +- .../calendars/edit/import_modal/utils.js | 2 +- .../plugins/xpack_main/jquery_flot.js | 11 +- 36 files changed, 1450 insertions(+), 1462 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1f42ff48b4dc9..9e3ab7cef8002 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -151,6 +151,16 @@ module.exports = { }, }, + /** + * New Platform client-side + */ + { + files: ['{src,x-pack}/plugins/*/public/**/*.{js,ts,tsx}'], + rules: { + 'import/no-commonjs': 'error', + }, + }, + /** * Files that require Elastic license headers instead of Apache 2.0 header */ diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx index cf62de82bcf4b..47f7aa1635205 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -24,7 +24,7 @@ import { parse } from 'query-string'; import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react'; import { useUIAceKeyboardMode } from '../../../../../../../es_ui_shared/public'; // @ts-ignore -import mappings from '../../../../../lib/mappings/mappings'; +import { retrieveAutoCompleteInfo, clearSubscriptions } from '../../../../../lib/mappings/mappings'; import { ConsoleMenu } from '../../../../components'; import { useEditorReadContext, useServicesContext } from '../../../../contexts'; import { @@ -172,14 +172,14 @@ function EditorUI({ initialTextValue }: EditorProps) { setInputEditor(editor); setTextArea(editorRef.current!.querySelector('textarea')); - mappings.retrieveAutoCompleteInfo(settingsService, settingsService.getAutocomplete()); + retrieveAutoCompleteInfo(settingsService, settingsService.getAutocomplete()); const unsubscribeResizer = subscribeResizeChecker(editorRef.current!, editor); setupAutosave(); return () => { unsubscribeResizer(); - mappings.clearSubscriptions(); + clearSubscriptions(); window.removeEventListener('hashchange', onHashChange); }; }, [saveCurrentTextObject, initialTextValue, history, setInputEditor, settingsService]); diff --git a/src/plugins/console/public/application/containers/settings.tsx b/src/plugins/console/public/application/containers/settings.tsx index e34cfcac8096b..81938a83435de 100644 --- a/src/plugins/console/public/application/containers/settings.tsx +++ b/src/plugins/console/public/application/containers/settings.tsx @@ -21,7 +21,7 @@ import React from 'react'; import { AutocompleteOptions, DevToolsSettingsModal } from '../components'; // @ts-ignore -import mappings from '../../lib/mappings/mappings'; +import { retrieveAutoCompleteInfo } from '../../lib/mappings/mappings'; import { useServicesContext, useEditorActionContext } from '../contexts'; import { DevToolsSettings, Settings as SettingsService } from '../../services'; @@ -33,7 +33,7 @@ const getAutocompleteDiff = (newSettings: DevToolsSettings, prevSettings: DevToo }; const refreshAutocompleteSettings = (settings: SettingsService, selectedSettings: any) => { - mappings.retrieveAutoCompleteInfo(settings, selectedSettings); + retrieveAutoCompleteInfo(settings, selectedSettings); }; const fetchAutocompleteSettingsIfNeeded = ( @@ -61,10 +61,10 @@ const fetchAutocompleteSettingsIfNeeded = ( }, {} ); - mappings.retrieveAutoCompleteInfo(settings, changedSettings); + retrieveAutoCompleteInfo(settings, changedSettings); } else if (isPollingChanged && newSettings.polling) { // If the user has turned polling on, then we'll fetch all selected autocomplete settings. - mappings.retrieveAutoCompleteInfo(settings, settings.getAutocomplete()); + retrieveAutoCompleteInfo(settings, settings.getAutocomplete()); } } }; diff --git a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts index dde793d9b9691..f0ce61f1d3401 100644 --- a/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts +++ b/src/plugins/console/public/application/hooks/use_send_current_request_to_es/use_send_current_request_to_es.ts @@ -24,7 +24,7 @@ import { sendRequestToES } from './send_request_to_es'; import { track } from './track'; // @ts-ignore -import mappings from '../../../lib/mappings/mappings'; +import { retrieveAutoCompleteInfo } from '../../../lib/mappings/mappings'; export const useSendCurrentRequestToES = () => { const { @@ -73,7 +73,7 @@ export const useSendCurrentRequestToES = () => { // or templates may have changed, so we'll need to update this data. Assume that if // the user disables polling they're trying to optimize performance or otherwise // preserve resources, so they won't want this request sent either. - mappings.retrieveAutoCompleteInfo(settings, settings.getAutocomplete()); + retrieveAutoCompleteInfo(settings, settings.getAutocomplete()); } dispatch({ diff --git a/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js b/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js index 5c86b0a1d2092..1db9ca7bc0a86 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/__tests__/output_tokenization.test.js @@ -17,7 +17,7 @@ * under the License. */ import '../legacy_core_editor.test.mocks'; -const $ = require('jquery'); +import $ from 'jquery'; import RowParser from '../../../../lib/row_parser'; import ace from 'brace'; import { createReadOnlyAceEditor } from '../create_readonly'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js index d763db7ae5d79..77b4ba8cea6ff 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js @@ -19,20 +19,21 @@ import ace from 'brace'; import { workerModule } from './worker'; +import { ScriptMode } from './script'; const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; -const ScriptMode = require('./script').ScriptMode; + const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; const WorkerClient = ace.acequire('ace/worker/worker_client').WorkerClient; const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; -const HighlightRules = require('./input_highlight_rules').InputHighlightRules; +import { InputHighlightRules } from './input_highlight_rules'; export function Mode() { - this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); + this.$tokenizer = new AceTokenizer(new InputHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js index 29f192f4ea858..1558cf0cb5554 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js @@ -17,7 +17,7 @@ * under the License. */ -const ace = require('brace'); +import ace from 'brace'; import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; export function addEOL(tokens, reg, nextIfEOL, normalNext) { diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output.js index 40e3128e396a3..5ad34532d1861 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output.js @@ -18,11 +18,11 @@ */ import ace from 'brace'; -require('./output_highlight_rules'); + +import { OutputJsonHighlightRules } from './output_highlight_rules'; const oop = ace.acequire('ace/lib/oop'); const JSONMode = ace.acequire('ace/mode/json').Mode; -const HighlightRules = require('./output_highlight_rules').OutputJsonHighlightRules; const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; @@ -30,7 +30,7 @@ ace.acequire('ace/worker/worker_client'); const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; export function Mode() { - this.$tokenizer = new AceTokenizer(new HighlightRules().getRules()); + this.$tokenizer = new AceTokenizer(new OutputJsonHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js index c9d538ab6ceb1..448fd847aeacd 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/output_highlight_rules.js @@ -17,7 +17,7 @@ * under the License. */ -const ace = require('brace'); +import ace from 'brace'; import 'brace/mode/json'; import { addXJsonToRules } from '../../../../../../es_ui_shared/public'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js b/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js index f79a171c65082..8a0eb9a03480b 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/theme_sense_dark.js @@ -18,7 +18,7 @@ */ /* eslint import/no-unresolved: 0 */ -const ace = require('brace'); +import ace from 'brace'; ace.define('ace/theme/sense-dark', ['require', 'exports', 'module'], function(require, exports) { exports.isDark = true; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/integration.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/integration.test.js index c5a0c2ebddf71..edd09885c1ad2 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/integration.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/integration.test.js @@ -19,10 +19,10 @@ import '../sense_editor.test.mocks'; import { create } from '../create'; import _ from 'lodash'; -const $ = require('jquery'); +import $ from 'jquery'; -const kb = require('../../../../lib/kb/kb'); -const mappings = require('../../../../lib/mappings/mappings'); +import * as kb from '../../../../lib/kb/kb'; +import * as mappings from '../../../../lib/mappings/mappings'; describe('Integration', () => { let senseEditor; diff --git a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js index 34b4cad7fbb6b..219e6262ab346 100644 --- a/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/__tests__/sense_editor.test.js @@ -23,7 +23,7 @@ import _ from 'lodash'; import { create } from '../create'; import { collapseLiteralStrings } from '../../../../../../es_ui_shared/public'; -const editorInput1 = require('./editor_input1.txt'); +import editorInput1 from './editor_input1.txt'; describe('Editor', () => { let input; diff --git a/src/plugins/console/public/lib/autocomplete/__jest__/url_autocomplete.test.js b/src/plugins/console/public/lib/autocomplete/__jest__/url_autocomplete.test.js index 0758a75695566..ebde8c39cffbc 100644 --- a/src/plugins/console/public/lib/autocomplete/__jest__/url_autocomplete.test.js +++ b/src/plugins/console/public/lib/autocomplete/__jest__/url_autocomplete.test.js @@ -17,7 +17,7 @@ * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; import { URL_PATH_END_MARKER, UrlPatternMatcher, diff --git a/src/plugins/console/public/lib/autocomplete/__jest__/url_params.test.js b/src/plugins/console/public/lib/autocomplete/__jest__/url_params.test.js index 72fce53c4f1fe..286aefcd133a0 100644 --- a/src/plugins/console/public/lib/autocomplete/__jest__/url_params.test.js +++ b/src/plugins/console/public/lib/autocomplete/__jest__/url_params.test.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; import { UrlParams } from '../../autocomplete/url_params'; import { populateContext } from '../../autocomplete/engine'; diff --git a/src/plugins/console/public/lib/autocomplete/body_completer.js b/src/plugins/console/public/lib/autocomplete/body_completer.js index 1aa315c50b9bf..9bb1f14a6266a 100644 --- a/src/plugins/console/public/lib/autocomplete/body_completer.js +++ b/src/plugins/console/public/lib/autocomplete/body_completer.js @@ -17,7 +17,7 @@ * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; import { WalkingState, walkTokenPath, wrapComponentWithDefaults } from './engine'; import { ConstantComponent, diff --git a/src/plugins/console/public/lib/autocomplete/components/field_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/field_autocomplete_component.js index 0574ffbcfc3a9..80f65406cf5d3 100644 --- a/src/plugins/console/public/lib/autocomplete/components/field_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/field_autocomplete_component.js @@ -17,11 +17,11 @@ * under the License. */ import _ from 'lodash'; -import mappings from '../../mappings/mappings'; +import { getFields } from '../../mappings/mappings'; import { ListComponent } from './list_component'; function FieldGenerator(context) { - return _.map(mappings.getFields(context.indices, context.types), function(field) { + return _.map(getFields(context.indices, context.types), function(field) { return { name: field.name, meta: field.type }; }); } diff --git a/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js index 03d67c9e27ee8..ec6f24253e78d 100644 --- a/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js @@ -17,14 +17,14 @@ * under the License. */ import _ from 'lodash'; -import mappings from '../../mappings/mappings'; +import { getIndices } from '../../mappings/mappings'; import { ListComponent } from './list_component'; function nonValidIndexType(token) { return !(token === '_all' || token[0] !== '_'); } export class IndexAutocompleteComponent extends ListComponent { constructor(name, parent, multiValued) { - super(name, mappings.getIndices, parent, multiValued); + super(name, getIndices, parent, multiValued); } validateTokens(tokens) { if (!this.multiValued && tokens.length > 1) { diff --git a/src/plugins/console/public/lib/autocomplete/components/template_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/template_autocomplete_component.js index cc62a2f9eeea6..14141980d493d 100644 --- a/src/plugins/console/public/lib/autocomplete/components/template_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/template_autocomplete_component.js @@ -16,12 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import mappings from '../../mappings/mappings'; +import { getTemplates } from '../../mappings/mappings'; import { ListComponent } from './list_component'; export class TemplateAutocompleteComponent extends ListComponent { constructor(name, parent) { - super(name, mappings.getTemplates, parent, true, true); + super(name, getTemplates, parent, true, true); } getContextKey() { return 'template'; diff --git a/src/plugins/console/public/lib/autocomplete/components/type_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/type_autocomplete_component.js index 507817c1ed8c5..03d85eccaf385 100644 --- a/src/plugins/console/public/lib/autocomplete/components/type_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/type_autocomplete_component.js @@ -18,9 +18,9 @@ */ import _ from 'lodash'; import { ListComponent } from './list_component'; -import mappings from '../../mappings/mappings'; +import { getTypes } from '../../mappings/mappings'; function TypeGenerator(context) { - return mappings.getTypes(context.indices); + return getTypes(context.indices); } function nonValidIndexType(token) { return !(token === '_all' || token[0] !== '_'); diff --git a/src/plugins/console/public/lib/autocomplete/components/username_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/username_autocomplete_component.js index 26b7bd5c48c99..14b77d4e70625 100644 --- a/src/plugins/console/public/lib/autocomplete/components/username_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/username_autocomplete_component.js @@ -17,14 +17,14 @@ * under the License. */ import _ from 'lodash'; -import mappings from '../../mappings/mappings'; +import { getIndices } from '../../mappings/mappings'; import { ListComponent } from './list_component'; function nonValidUsernameType(token) { return token[0] === '_'; } export class UsernameAutocompleteComponent extends ListComponent { constructor(name, parent, multiValued) { - super(name, mappings.getIndices, parent, multiValued); + super(name, getIndices, parent, multiValued); } validateTokens(tokens) { if (!this.multiValued && tokens.length > 1) { diff --git a/src/plugins/console/public/lib/autocomplete/engine.js b/src/plugins/console/public/lib/autocomplete/engine.js index 7b64d91c95374..ae943a74ffb3a 100644 --- a/src/plugins/console/public/lib/autocomplete/engine.js +++ b/src/plugins/console/public/lib/autocomplete/engine.js @@ -17,7 +17,7 @@ * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; export function wrapComponentWithDefaults(component, defaults) { const originalGetTerms = component.getTerms; diff --git a/src/plugins/console/public/lib/autocomplete/url_params.js b/src/plugins/console/public/lib/autocomplete/url_params.js index 3f05b9ce85aab..0519a2daade87 100644 --- a/src/plugins/console/public/lib/autocomplete/url_params.js +++ b/src/plugins/console/public/lib/autocomplete/url_params.js @@ -17,7 +17,7 @@ * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; import { ConstantComponent, ListComponent, SharedComponent } from './components'; export class ParamComponent extends ConstantComponent { diff --git a/src/plugins/console/public/lib/curl_parsing/__tests__/curl_parsing.test.js b/src/plugins/console/public/lib/curl_parsing/__tests__/curl_parsing.test.js index 49a54eaefa9ef..6a8caebfc6874 100644 --- a/src/plugins/console/public/lib/curl_parsing/__tests__/curl_parsing.test.js +++ b/src/plugins/console/public/lib/curl_parsing/__tests__/curl_parsing.test.js @@ -17,15 +17,15 @@ * under the License. */ -const _ = require('lodash'); -const curl = require('../curl'); +import _ from 'lodash'; +import { detectCURL, parseCURL } from '../curl'; import curlTests from './curl_parsing.txt'; describe('CURL', () => { const notCURLS = ['sldhfsljfhs', 's;kdjfsldkfj curl -XDELETE ""', '{ "hello": 1 }']; _.each(notCURLS, function(notCURL, i) { test('cURL Detection - broken strings ' + i, function() { - expect(curl.detectCURL(notCURL)).toEqual(false); + expect(detectCURL(notCURL)).toEqual(false); }); }); @@ -39,8 +39,8 @@ describe('CURL', () => { const response = fixture[2].trim(); test('cURL Detection - ' + name, function() { - expect(curl.detectCURL(curlText)).toBe(true); - const r = curl.parseCURL(curlText); + expect(detectCURL(curlText)).toBe(true); + const r = parseCURL(curlText); expect(r).toEqual(response); }); }); diff --git a/src/plugins/console/public/lib/kb/__tests__/kb.test.js b/src/plugins/console/public/lib/kb/__tests__/kb.test.js index c2c69314a172d..c80f5671449b3 100644 --- a/src/plugins/console/public/lib/kb/__tests__/kb.test.js +++ b/src/plugins/console/public/lib/kb/__tests__/kb.test.js @@ -21,8 +21,8 @@ import _ from 'lodash'; import { populateContext } from '../../autocomplete/engine'; import '../../../application/models/sense_editor/sense_editor.test.mocks'; -const kb = require('../../kb'); -const mappings = require('../../mappings/mappings'); +import * as kb from '../../kb'; +import * as mappings from '../../mappings/mappings'; describe('Knowledge base', () => { beforeEach(() => { diff --git a/src/plugins/console/public/lib/kb/api.js b/src/plugins/console/public/lib/kb/api.js index eeec87060b770..c418a7cb414ef 100644 --- a/src/plugins/console/public/lib/kb/api.js +++ b/src/plugins/console/public/lib/kb/api.js @@ -17,7 +17,7 @@ * under the License. */ -const _ = require('lodash'); +import _ from 'lodash'; import { UrlPatternMatcher } from '../autocomplete/components'; import { UrlParams } from '../autocomplete/url_params'; import { diff --git a/src/plugins/console/public/lib/mappings/__tests__/mapping.test.js b/src/plugins/console/public/lib/mappings/__tests__/mapping.test.js index 27b3ce26b5588..292b1b4fb1bf5 100644 --- a/src/plugins/console/public/lib/mappings/__tests__/mapping.test.js +++ b/src/plugins/console/public/lib/mappings/__tests__/mapping.test.js @@ -17,7 +17,7 @@ * under the License. */ import '../../../application/models/sense_editor/sense_editor.test.mocks'; -const mappings = require('../mappings'); +import * as mappings from '../mappings'; describe('Mappings', () => { beforeEach(() => { diff --git a/src/plugins/console/public/lib/mappings/mappings.js b/src/plugins/console/public/lib/mappings/mappings.js index 330147118d42c..b5bcc2b105996 100644 --- a/src/plugins/console/public/lib/mappings/mappings.js +++ b/src/plugins/console/public/lib/mappings/mappings.js @@ -17,9 +17,9 @@ * under the License. */ -const $ = require('jquery'); -const _ = require('lodash'); -const es = require('../es/es'); +import $ from 'jquery'; +import _ from 'lodash'; +import * as es from '../es/es'; // NOTE: If this value ever changes to be a few seconds or less, it might introduce flakiness // due to timing issues in our app.js tests. @@ -32,7 +32,7 @@ let templates = []; const mappingObj = {}; -function expandAliases(indicesOrAliases) { +export function expandAliases(indicesOrAliases) { // takes a list of indices or aliases or a string which may be either and returns a list of indices // returns a list for multiple values or a string for a single. @@ -60,11 +60,11 @@ function expandAliases(indicesOrAliases) { return ret.length > 1 ? ret : ret[0]; } -function getTemplates() { +export function getTemplates() { return [...templates]; } -function getFields(indices, types) { +export function getFields(indices, types) { // get fields for indices and types. Both can be a list, a string or null (meaning all). let ret = []; indices = expandAliases(indices); @@ -103,7 +103,7 @@ function getFields(indices, types) { }); } -function getTypes(indices) { +export function getTypes(indices) { let ret = []; indices = expandAliases(indices); if (typeof indices === 'string') { @@ -129,7 +129,7 @@ function getTypes(indices) { return _.uniq(ret); } -function getIndices(includeAliases) { +export function getIndices(includeAliases) { const ret = []; $.each(perIndexTypes, function(index) { ret.push(index); @@ -200,7 +200,7 @@ function loadTemplates(templatesObject = {}) { templates = Object.keys(templatesObject); } -function loadMappings(mappings) { +export function loadMappings(mappings) { perIndexTypes = {}; $.each(mappings, function(index, indexMapping) { @@ -224,7 +224,7 @@ function loadMappings(mappings) { }); } -function loadAliases(aliases) { +export function loadAliases(aliases) { perAliasIndexes = {}; $.each(aliases || {}, function(index, omdexAliases) { // verify we have an index defined. useful when mapping loading is disabled @@ -246,7 +246,7 @@ function loadAliases(aliases) { perAliasIndexes._all = getIndices(false); } -function clear() { +export function clear() { perIndexTypes = {}; perAliasIndexes = {}; templates = []; @@ -285,7 +285,7 @@ function retrieveSettings(settingsKey, settingsToRetrieve) { // unchanged alone (both selected and unselected). // 3. Poll: Use saved. Fetch selected. Ignore unselected. -function clearSubscriptions() { +export function clearSubscriptions() { if (pollTimeoutId) { clearTimeout(pollTimeoutId); } @@ -296,7 +296,7 @@ function clearSubscriptions() { * @param settings Settings A way to retrieve the current settings * @param settingsToRetrieve any */ -function retrieveAutoCompleteInfo(settings, settingsToRetrieve) { +export function retrieveAutoCompleteInfo(settings, settingsToRetrieve) { clearSubscriptions(); const mappingPromise = retrieveSettings('fields', settingsToRetrieve); @@ -341,16 +341,3 @@ function retrieveAutoCompleteInfo(settings, settingsToRetrieve) { }, POLL_INTERVAL); }); } - -export default { - getFields, - getTemplates, - getIndices, - getTypes, - loadMappings, - loadAliases, - expandAliases, - clear, - retrieveAutoCompleteInfo, - clearSubscriptions, -}; diff --git a/src/plugins/console/public/lib/utils/__tests__/utils.test.js b/src/plugins/console/public/lib/utils/__tests__/utils.test.js index 6115be3c84ed9..3a2e6a54c1328 100644 --- a/src/plugins/console/public/lib/utils/__tests__/utils.test.js +++ b/src/plugins/console/public/lib/utils/__tests__/utils.test.js @@ -17,7 +17,7 @@ * under the License. */ -const utils = require('../'); +import * as utils from '../'; describe('Utils class', () => { test('extract deprecation messages', function() { diff --git a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.ts b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.ts index ff051d470531b..ce40a0e46b0a0 100644 --- a/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.ts +++ b/x-pack/plugins/cross_cluster_replication/public/__jest__/client_integration/fixtures/follower_index.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import Chance from 'chance'; import { getRandomString } from '../../../../../../test_utils'; import { FollowerIndex } from '../../../../common/types'; -const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies, @typescript-eslint/no-var-requires const chance = new Chance(); interface FollowerIndexMock { diff --git a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js index 90538ae652c08..872df0cddca3c 100644 --- a/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js +++ b/x-pack/plugins/file_upload/public/util/geo_json_clean_and_validate.test.js @@ -5,7 +5,7 @@ */ import { cleanGeometry, geoJsonCleanAndValidate } from './geo_json_clean_and_validate'; -const jsts = require('jsts'); +import * as jsts from 'jsts'; describe('geo_json_clean_and_validate', () => { const reader = new jsts.io.GeoJSONReader(); diff --git a/x-pack/plugins/file_upload/public/util/pattern_reader.js b/x-pack/plugins/file_upload/public/util/pattern_reader.js index 78f1c4f217519..152e0f7e54580 100644 --- a/x-pack/plugins/file_upload/public/util/pattern_reader.js +++ b/x-pack/plugins/file_upload/public/util/pattern_reader.js @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -const oboe = require('oboe'); +import oboe from 'oboe'; export class PatternReader { constructor({ onFeatureDetect, onStreamComplete }) { diff --git a/x-pack/plugins/graph/public/angular/graph_client_workspace.js b/x-pack/plugins/graph/public/angular/graph_client_workspace.js index a7d98a42404ec..bcd31716b6d64 100644 --- a/x-pack/plugins/graph/public/angular/graph_client_workspace.js +++ b/x-pack/plugins/graph/public/angular/graph_client_workspace.js @@ -7,1576 +7,1569 @@ import $ from 'jquery'; // Kibana wrapper -const d3 = require('d3'); - -module.exports = (function() { - // Pluggable function to handle the comms with a server. Default impl here is - // for use outside of Kibana server with direct access to elasticsearch - let graphExplorer = function(indexName, typeName, request, responseHandler) { - const dataForServer = JSON.stringify(request); - $.ajax({ - type: 'POST', - url: 'http://localhost:9200/' + indexName + '/_graph/explore', - dataType: 'json', - contentType: 'application/json;charset=utf-8', - async: true, - data: dataForServer, - success: function(data) { - responseHandler(data); - }, - }); +import d3 from 'd3'; + +// Pluggable function to handle the comms with a server. Default impl here is +// for use outside of Kibana server with direct access to elasticsearch +let graphExplorer = function(indexName, typeName, request, responseHandler) { + const dataForServer = JSON.stringify(request); + $.ajax({ + type: 'POST', + url: 'http://localhost:9200/' + indexName + '/_graph/explore', + dataType: 'json', + contentType: 'application/json;charset=utf-8', + async: true, + data: dataForServer, + success: function(data) { + responseHandler(data); + }, + }); +}; +let searcher = function(indexName, request, responseHandler) { + const dataForServer = JSON.stringify(request); + $.ajax({ + type: 'POST', + url: 'http://localhost:9200/' + indexName + '/_search?rest_total_hits_as_int=true', + dataType: 'json', + contentType: 'application/json;charset=utf-8', //Not sure why this was necessary - worked without elsewhere + async: true, + data: dataForServer, + success: function(data) { + responseHandler(data); + }, + }); +}; + +// ====== Undo operations ============= + +function AddNodeOperation(node, owner) { + const self = this; + const vm = owner; + self.node = node; + self.undo = function() { + vm.arrRemove(vm.nodes, self.node); + vm.arrRemove(vm.selectedNodes, self.node); + self.node.isSelected = false; + + delete vm.nodesMap[self.node.id]; }; - let searcher = function(indexName, request, responseHandler) { - const dataForServer = JSON.stringify(request); - $.ajax({ - type: 'POST', - url: 'http://localhost:9200/' + indexName + '/_search?rest_total_hits_as_int=true', - dataType: 'json', - contentType: 'application/json;charset=utf-8', //Not sure why this was necessary - worked without elsewhere - async: true, - data: dataForServer, - success: function(data) { - responseHandler(data); - }, - }); + self.redo = function() { + vm.nodes.push(self.node); + vm.nodesMap[self.node.id] = self.node; }; - - // ====== Undo operations ============= - - function AddNodeOperation(node, owner) { - const self = this; - const vm = owner; - self.node = node; - self.undo = function() { - vm.arrRemove(vm.nodes, self.node); - vm.arrRemove(vm.selectedNodes, self.node); - self.node.isSelected = false; - - delete vm.nodesMap[self.node.id]; - }; - self.redo = function() { - vm.nodes.push(self.node); - vm.nodesMap[self.node.id] = self.node; - }; - } - - function AddEdgeOperation(edge, owner) { - const self = this; - const vm = owner; - self.edge = edge; - self.undo = function() { - vm.arrRemove(vm.edges, self.edge); - delete vm.edgesMap[self.edge.id]; - }; - self.redo = function() { - vm.edges.push(self.edge); - vm.edgesMap[self.edge.id] = self.edge; - }; - } - - function ReverseOperation(operation) { - const self = this; - const reverseOperation = operation; - self.undo = reverseOperation.redo; - self.redo = reverseOperation.undo; - } - - function GroupOperation(receiver, orphan) { - const self = this; - self.receiver = receiver; - self.orphan = orphan; - self.undo = function() { - self.orphan.parent = undefined; - }; - self.redo = function() { - self.orphan.parent = self.receiver; - }; +} + +function AddEdgeOperation(edge, owner) { + const self = this; + const vm = owner; + self.edge = edge; + self.undo = function() { + vm.arrRemove(vm.edges, self.edge); + delete vm.edgesMap[self.edge.id]; + }; + self.redo = function() { + vm.edges.push(self.edge); + vm.edgesMap[self.edge.id] = self.edge; + }; +} + +function ReverseOperation(operation) { + const self = this; + const reverseOperation = operation; + self.undo = reverseOperation.redo; + self.redo = reverseOperation.undo; +} + +function GroupOperation(receiver, orphan) { + const self = this; + self.receiver = receiver; + self.orphan = orphan; + self.undo = function() { + self.orphan.parent = undefined; + }; + self.redo = function() { + self.orphan.parent = self.receiver; + }; +} + +function UnGroupOperation(parent, child) { + const self = this; + self.parent = parent; + self.child = child; + self.undo = function() { + self.child.parent = self.parent; + }; + self.redo = function() { + self.child.parent = undefined; + }; +} + +// The main constructor for our GraphWorkspace +function GraphWorkspace(options) { + const self = this; + this.blacklistedNodes = []; + this.options = options; + this.undoLog = []; + this.redoLog = []; + this.selectedNodes = []; + + if (!options) { + this.options = {}; } - - function UnGroupOperation(parent, child) { - const self = this; - self.parent = parent; - self.child = child; - self.undo = function() { - self.child.parent = self.parent; - }; - self.redo = function() { - self.child.parent = undefined; - }; + this.nodesMap = {}; + this.edgesMap = {}; + this.searchTerm = ''; + + //A sequence number used to know when a node was added + this.seqNumber = 0; + + this.nodes = []; + this.edges = []; + this.lastRequest = null; + this.lastResponse = null; + this.changeHandler = options.changeHandler; + if (options.graphExploreProxy) { + graphExplorer = options.graphExploreProxy; } - - function createWorkspace(options) { - return new GraphWorkspace(options); + if (options.searchProxy) { + searcher = options.searchProxy; } - // The main constructor for our GraphWorkspace - function GraphWorkspace(options) { - const self = this; - this.blacklistedNodes = []; - this.options = options; - this.undoLog = []; - this.redoLog = []; - this.selectedNodes = []; - - if (!options) { - this.options = {}; + this.addUndoLogEntry = function(undoOperations) { + self.undoLog.push(undoOperations); + if (self.undoLog.length > 50) { + //Remove the oldest + self.undoLog.splice(0, 1); } - this.nodesMap = {}; - this.edgesMap = {}; - this.searchTerm = ''; - - //A sequence number used to know when a node was added - this.seqNumber = 0; + self.redoLog = []; + }; - this.nodes = []; - this.edges = []; - this.lastRequest = null; - this.lastResponse = null; - this.changeHandler = options.changeHandler; - if (options.graphExploreProxy) { - graphExplorer = options.graphExploreProxy; + this.undo = function() { + const lastOps = this.undoLog.pop(); + if (lastOps) { + this.stopLayout(); + this.redoLog.push(lastOps); + lastOps.forEach(ops => ops.undo()); + this.runLayout(); } - if (options.searchProxy) { - searcher = options.searchProxy; + }; + this.redo = function() { + const lastOps = this.redoLog.pop(); + if (lastOps) { + this.stopLayout(); + this.undoLog.push(lastOps); + lastOps.forEach(ops => ops.redo()); + this.runLayout(); } + }; - this.addUndoLogEntry = function(undoOperations) { - self.undoLog.push(undoOperations); - if (self.undoLog.length > 50) { - //Remove the oldest - self.undoLog.splice(0, 1); + //Determines if 2 nodes are connected via an edge + this.areLinked = function(a, b) { + if (a === b) return true; + this.edges.forEach(e => { + if (e.source === a && e.target === b) { + return true; } - self.redoLog = []; - }; - - this.undo = function() { - const lastOps = this.undoLog.pop(); - if (lastOps) { - this.stopLayout(); - this.redoLog.push(lastOps); - lastOps.forEach(ops => ops.undo()); - this.runLayout(); + if (e.source === b && e.target === a) { + return true; } - }; - this.redo = function() { - const lastOps = this.redoLog.pop(); - if (lastOps) { - this.stopLayout(); - this.undoLog.push(lastOps); - lastOps.forEach(ops => ops.redo()); - this.runLayout(); - } - }; - - //Determines if 2 nodes are connected via an edge - this.areLinked = function(a, b) { - if (a === b) return true; - this.edges.forEach(e => { - if (e.source === a && e.target === b) { - return true; - } - if (e.source === b && e.target === a) { - return true; - } - }); - return false; - }; + }); + return false; + }; - //======== Selection functions ======== + //======== Selection functions ======== - this.selectAll = function() { - self.selectedNodes = []; - self.nodes.forEach(node => { - if (node.parent === undefined) { - node.isSelected = true; - self.selectedNodes.push(node); - } else { - node.isSelected = false; - } - }); - }; - - this.selectNone = function() { - self.selectedNodes = []; - self.nodes.forEach(node => { + this.selectAll = function() { + self.selectedNodes = []; + self.nodes.forEach(node => { + if (node.parent === undefined) { + node.isSelected = true; + self.selectedNodes.push(node); + } else { node.isSelected = false; - }); - }; + } + }); + }; - this.selectInvert = function() { - self.selectedNodes = []; - self.nodes.forEach(node => { - if (node.parent !== undefined) { - return; - } - node.isSelected = !node.isSelected; - if (node.isSelected) { - self.selectedNodes.push(node); - } - }); - }; + this.selectNone = function() { + self.selectedNodes = []; + self.nodes.forEach(node => { + node.isSelected = false; + }); + }; - this.selectNodes = function(nodes) { - nodes.forEach(node => { - node.isSelected = true; - if (self.selectedNodes.indexOf(node) < 0) { - self.selectedNodes.push(node); - } - }); - }; + this.selectInvert = function() { + self.selectedNodes = []; + self.nodes.forEach(node => { + if (node.parent !== undefined) { + return; + } + node.isSelected = !node.isSelected; + if (node.isSelected) { + self.selectedNodes.push(node); + } + }); + }; - this.selectNode = function(node) { + this.selectNodes = function(nodes) { + nodes.forEach(node => { node.isSelected = true; if (self.selectedNodes.indexOf(node) < 0) { self.selectedNodes.push(node); } - }; + }); + }; - this.deleteSelection = function() { - let allAndGrouped = self.returnUnpackedGroupeds(self.selectedNodes); + this.selectNode = function(node) { + node.isSelected = true; + if (self.selectedNodes.indexOf(node) < 0) { + self.selectedNodes.push(node); + } + }; - // Nothing selected so process all nodes - if (allAndGrouped.length === 0) { - allAndGrouped = self.nodes.slice(0); - } + this.deleteSelection = function() { + let allAndGrouped = self.returnUnpackedGroupeds(self.selectedNodes); - const undoOperations = []; - allAndGrouped.forEach(node => { - //We set selected to false because despite being deleted, node objects sit in an undo log - node.isSelected = false; - delete self.nodesMap[node.id]; - undoOperations.push(new ReverseOperation(new AddNodeOperation(node, self))); - }); - self.arrRemoveAll(self.nodes, allAndGrouped); - self.arrRemoveAll(self.selectedNodes, allAndGrouped); + // Nothing selected so process all nodes + if (allAndGrouped.length === 0) { + allAndGrouped = self.nodes.slice(0); + } - const danglingEdges = self.edges.filter(function(edge) { - return self.nodes.indexOf(edge.source) < 0 || self.nodes.indexOf(edge.target) < 0; - }); - danglingEdges.forEach(edge => { - delete self.edgesMap[edge.id]; - undoOperations.push(new ReverseOperation(new AddEdgeOperation(edge, self))); - }); - self.addUndoLogEntry(undoOperations); - self.arrRemoveAll(self.edges, danglingEdges); - self.runLayout(); - }; + const undoOperations = []; + allAndGrouped.forEach(node => { + //We set selected to false because despite being deleted, node objects sit in an undo log + node.isSelected = false; + delete self.nodesMap[node.id]; + undoOperations.push(new ReverseOperation(new AddNodeOperation(node, self))); + }); + self.arrRemoveAll(self.nodes, allAndGrouped); + self.arrRemoveAll(self.selectedNodes, allAndGrouped); - this.selectNeighbours = function() { - const newSelections = []; - self.edges.forEach(edge => { - if (!edge.topSrc.isSelected) { - if (self.selectedNodes.indexOf(edge.topTarget) >= 0) { - if (newSelections.indexOf(edge.topSrc) < 0) { - newSelections.push(edge.topSrc); - } + const danglingEdges = self.edges.filter(function(edge) { + return self.nodes.indexOf(edge.source) < 0 || self.nodes.indexOf(edge.target) < 0; + }); + danglingEdges.forEach(edge => { + delete self.edgesMap[edge.id]; + undoOperations.push(new ReverseOperation(new AddEdgeOperation(edge, self))); + }); + self.addUndoLogEntry(undoOperations); + self.arrRemoveAll(self.edges, danglingEdges); + self.runLayout(); + }; + + this.selectNeighbours = function() { + const newSelections = []; + self.edges.forEach(edge => { + if (!edge.topSrc.isSelected) { + if (self.selectedNodes.indexOf(edge.topTarget) >= 0) { + if (newSelections.indexOf(edge.topSrc) < 0) { + newSelections.push(edge.topSrc); } } - if (!edge.topTarget.isSelected) { - if (self.selectedNodes.indexOf(edge.topSrc) >= 0) { - if (newSelections.indexOf(edge.topTarget) < 0) { - newSelections.push(edge.topTarget); - } + } + if (!edge.topTarget.isSelected) { + if (self.selectedNodes.indexOf(edge.topSrc) >= 0) { + if (newSelections.indexOf(edge.topTarget) < 0) { + newSelections.push(edge.topTarget); } } - }); - newSelections.forEach(newlySelectedNode => { - self.selectedNodes.push(newlySelectedNode); - newlySelectedNode.isSelected = true; - }); - }; - - this.selectNone = function() { - self.selectedNodes.forEach(node => { - node.isSelected = false; - }); - self.selectedNodes = []; - }; + } + }); + newSelections.forEach(newlySelectedNode => { + self.selectedNodes.push(newlySelectedNode); + newlySelectedNode.isSelected = true; + }); + }; - this.deselectNode = function(node) { + this.selectNone = function() { + self.selectedNodes.forEach(node => { node.isSelected = false; - self.arrRemove(self.selectedNodes, node); - }; - - this.getAllSelectedNodes = function() { - return this.returnUnpackedGroupeds(self.selectedNodes); - }; + }); + self.selectedNodes = []; + }; - this.colorSelected = function(colorNum) { - self.getAllSelectedNodes().forEach(node => { - node.color = colorNum; - }); - }; + this.deselectNode = function(node) { + node.isSelected = false; + self.arrRemove(self.selectedNodes, node); + }; - this.getSelectionsThatAreGrouped = function() { - const result = []; - self.selectedNodes.forEach(node => { - if (node.numChildren > 0) { - result.push(node); - } - }); - return result; - }; + this.getAllSelectedNodes = function() { + return this.returnUnpackedGroupeds(self.selectedNodes); + }; - this.ungroupSelection = function() { - self.getSelectionsThatAreGrouped().forEach(node => { - self.ungroup(node); - }); - }; + this.colorSelected = function(colorNum) { + self.getAllSelectedNodes().forEach(node => { + node.color = colorNum; + }); + }; - this.toggleNodeSelection = function(node) { - if (node.isSelected) { - self.deselectNode(node); - } else { - node.isSelected = true; - self.selectedNodes.push(node); + this.getSelectionsThatAreGrouped = function() { + const result = []; + self.selectedNodes.forEach(node => { + if (node.numChildren > 0) { + result.push(node); } - return node.isSelected; - }; + }); + return result; + }; - this.returnUnpackedGroupeds = function(topLevelNodeArray) { - //Gather any grouped nodes that are part of this top-level selection - const result = topLevelNodeArray.slice(); + this.ungroupSelection = function() { + self.getSelectionsThatAreGrouped().forEach(node => { + self.ungroup(node); + }); + }; - // We iterate over edges not nodes because edges conveniently hold the top-most - // node information. + this.toggleNodeSelection = function(node) { + if (node.isSelected) { + self.deselectNode(node); + } else { + node.isSelected = true; + self.selectedNodes.push(node); + } + return node.isSelected; + }; - const edges = this.edges; - for (let i = 0; i < edges.length; i++) { - const edge = edges[i]; + this.returnUnpackedGroupeds = function(topLevelNodeArray) { + //Gather any grouped nodes that are part of this top-level selection + const result = topLevelNodeArray.slice(); - const topLevelSource = edge.topSrc; - const topLevelTarget = edge.topTarget; + // We iterate over edges not nodes because edges conveniently hold the top-most + // node information. - if (result.indexOf(topLevelTarget) >= 0) { - //visible top-level node is selected - add all nesteds starting from bottom up - let target = edge.target; - while (target.parent !== undefined) { - if (result.indexOf(target) < 0) { - result.push(target); - } - target = target.parent; + const edges = this.edges; + for (let i = 0; i < edges.length; i++) { + const edge = edges[i]; + + const topLevelSource = edge.topSrc; + const topLevelTarget = edge.topTarget; + + if (result.indexOf(topLevelTarget) >= 0) { + //visible top-level node is selected - add all nesteds starting from bottom up + let target = edge.target; + while (target.parent !== undefined) { + if (result.indexOf(target) < 0) { + result.push(target); } + target = target.parent; } + } - if (result.indexOf(topLevelSource) >= 0) { - //visible top-level node is selected - add all nesteds starting from bottom up - let source = edge.source; - while (source.parent !== undefined) { - if (result.indexOf(source) < 0) { - result.push(source); - } - source = source.parent; + if (result.indexOf(topLevelSource) >= 0) { + //visible top-level node is selected - add all nesteds starting from bottom up + let source = edge.source; + while (source.parent !== undefined) { + if (result.indexOf(source) < 0) { + result.push(source); } + source = source.parent; } - } //end of edges loop + } + } //end of edges loop - return result; - }; + return result; + }; - // ======= Miscellaneous functions + // ======= Miscellaneous functions - this.clearGraph = function() { - this.stopLayout(); - this.nodes = []; - this.edges = []; - this.undoLog = []; - this.redoLog = []; - this.nodesMap = {}; - this.edgesMap = {}; - this.blacklistedNodes = []; - this.selectedNodes = []; - this.lastResponse = null; - }; + this.clearGraph = function() { + this.stopLayout(); + this.nodes = []; + this.edges = []; + this.undoLog = []; + this.redoLog = []; + this.nodesMap = {}; + this.edgesMap = {}; + this.blacklistedNodes = []; + this.selectedNodes = []; + this.lastResponse = null; + }; - this.arrRemoveAll = function remove(arr, items) { - for (let i = items.length; i--; ) { - self.arrRemove(arr, items[i]); - } - }; + this.arrRemoveAll = function remove(arr, items) { + for (let i = items.length; i--; ) { + self.arrRemove(arr, items[i]); + } + }; - this.arrRemove = function remove(arr, item) { - for (let i = arr.length; i--; ) { - if (arr[i] === item) { - arr.splice(i, 1); - } + this.arrRemove = function remove(arr, item) { + for (let i = arr.length; i--; ) { + if (arr[i] === item) { + arr.splice(i, 1); } - }; + } + }; - this.getNeighbours = function(node) { - const neighbourNodes = []; - self.edges.forEach(edge => { - if (edge.topSrc === edge.topTarget) { - return; - } - if (edge.topSrc === node) { - if (neighbourNodes.indexOf(edge.topTarget) < 0) { - neighbourNodes.push(edge.topTarget); - } - } - if (edge.topTarget === node) { - if (neighbourNodes.indexOf(edge.topSrc) < 0) { - neighbourNodes.push(edge.topSrc); - } + this.getNeighbours = function(node) { + const neighbourNodes = []; + self.edges.forEach(edge => { + if (edge.topSrc === edge.topTarget) { + return; + } + if (edge.topSrc === node) { + if (neighbourNodes.indexOf(edge.topTarget) < 0) { + neighbourNodes.push(edge.topTarget); } - }); - return neighbourNodes; - }; - - //Creates a query that represents a node - either simple term query or boolean if grouped - this.buildNodeQuery = function(topLevelNode) { - let containedNodes = [topLevelNode]; - containedNodes = self.returnUnpackedGroupeds(containedNodes); - if (containedNodes.length === 1) { - //Simple case - return a single-term query - const tq = {}; - tq[topLevelNode.data.field] = topLevelNode.data.term; - return { - term: tq, - }; } - const termsByField = {}; - containedNodes.forEach(node => { - let termsList = termsByField[node.data.field]; - if (!termsList) { - termsList = []; - termsByField[node.data.field] = termsList; + if (edge.topTarget === node) { + if (neighbourNodes.indexOf(edge.topSrc) < 0) { + neighbourNodes.push(edge.topSrc); } - termsList.push(node.data.term); - }); - //Single field case - if (Object.keys(termsByField).length === 1) { - return { - terms: termsByField, - }; } - //Multi-field case - build a bool query with per-field terms clauses. - const q = { - bool: { - should: [], - }, + }); + return neighbourNodes; + }; + + //Creates a query that represents a node - either simple term query or boolean if grouped + this.buildNodeQuery = function(topLevelNode) { + let containedNodes = [topLevelNode]; + containedNodes = self.returnUnpackedGroupeds(containedNodes); + if (containedNodes.length === 1) { + //Simple case - return a single-term query + const tq = {}; + tq[topLevelNode.data.field] = topLevelNode.data.term; + return { + term: tq, }; - for (const field in termsByField) { - if (termsByField.hasOwnProperty(field)) { - const tq = {}; - tq[field] = termsByField[field]; - q.bool.should.push({ - terms: tq, - }); - } + } + const termsByField = {}; + containedNodes.forEach(node => { + let termsList = termsByField[node.data.field]; + if (!termsList) { + termsList = []; + termsByField[node.data.field] = termsList; } - return q; + termsList.push(node.data.term); + }); + //Single field case + if (Object.keys(termsByField).length === 1) { + return { + terms: termsByField, + }; + } + //Multi-field case - build a bool query with per-field terms clauses. + const q = { + bool: { + should: [], + }, }; + for (const field in termsByField) { + if (termsByField.hasOwnProperty(field)) { + const tq = {}; + tq[field] = termsByField[field]; + q.bool.should.push({ + terms: tq, + }); + } + } + return q; + }; - //====== Layout functions ======== + //====== Layout functions ======== - this.stopLayout = function() { - if (this.force) { - this.force.stop(); - } - this.force = null; - }; + this.stopLayout = function() { + if (this.force) { + this.force.stop(); + } + this.force = null; + }; - this.runLayout = function() { - this.stopLayout(); - // The set of nodes and edges we present to the d3 layout algorithms - // is potentially a reduced set of nodes if the client has used any - // grouping of nodes into parent nodes. - const effectiveEdges = []; - self.edges.forEach(edge => { - let topSrc = edge.source; - let topTarget = edge.target; - while (topSrc.parent !== undefined) { - topSrc = topSrc.parent; - } - while (topTarget.parent !== undefined) { - topTarget = topTarget.parent; - } - edge.topSrc = topSrc; - edge.topTarget = topTarget; + this.runLayout = function() { + this.stopLayout(); + // The set of nodes and edges we present to the d3 layout algorithms + // is potentially a reduced set of nodes if the client has used any + // grouping of nodes into parent nodes. + const effectiveEdges = []; + self.edges.forEach(edge => { + let topSrc = edge.source; + let topTarget = edge.target; + while (topSrc.parent !== undefined) { + topSrc = topSrc.parent; + } + while (topTarget.parent !== undefined) { + topTarget = topTarget.parent; + } + edge.topSrc = topSrc; + edge.topTarget = topTarget; - if (topSrc !== topTarget) { - effectiveEdges.push({ - source: topSrc, - target: topTarget, - }); - } - }); - const visibleNodes = self.nodes.filter(function(n) { - return n.parent === undefined; - }); - //reset then roll-up all the counts - const allNodes = self.nodes; - allNodes.forEach(node => { - node.numChildren = 0; - }); + if (topSrc !== topTarget) { + effectiveEdges.push({ + source: topSrc, + target: topTarget, + }); + } + }); + const visibleNodes = self.nodes.filter(function(n) { + return n.parent === undefined; + }); + //reset then roll-up all the counts + const allNodes = self.nodes; + allNodes.forEach(node => { + node.numChildren = 0; + }); - for (const n in allNodes) { - if (!allNodes.hasOwnProperty(n)) { - continue; - } - let node = allNodes[n]; - while (node.parent !== undefined) { - node = node.parent; - node.numChildren = node.numChildren + 1; - } + for (const n in allNodes) { + if (!allNodes.hasOwnProperty(n)) { + continue; + } + let node = allNodes[n]; + while (node.parent !== undefined) { + node = node.parent; + node.numChildren = node.numChildren + 1; } - this.force = d3.layout - .force() - .nodes(visibleNodes) - .links(effectiveEdges) - .friction(0.8) - .linkDistance(100) - .charge(-1500) - .gravity(0.15) - .theta(0.99) - .alpha(0.5) - .size([800, 600]) - .on('tick', function() { - const nodeArray = self.nodes; - let hasRollups = false; - //Update the position of all "top level nodes" + } + this.force = d3.layout + .force() + .nodes(visibleNodes) + .links(effectiveEdges) + .friction(0.8) + .linkDistance(100) + .charge(-1500) + .gravity(0.15) + .theta(0.99) + .alpha(0.5) + .size([800, 600]) + .on('tick', function() { + const nodeArray = self.nodes; + let hasRollups = false; + //Update the position of all "top level nodes" + nodeArray.forEach(n => { + //Code to support roll-ups + if (n.parent === undefined) { + n.kx = n.x; + n.ky = n.y; + } else { + hasRollups = true; + } + }); + if (hasRollups) { nodeArray.forEach(n => { //Code to support roll-ups - if (n.parent === undefined) { - n.kx = n.x; - n.ky = n.y; - } else { - hasRollups = true; - } - }); - if (hasRollups) { - nodeArray.forEach(n => { - //Code to support roll-ups - if (n.parent !== undefined) { - // Is a grouped node - inherit parent's position so edges point into parent - // d3 thinks it has moved it to x and y but we have final say using kx and ky. - let topLevelNode = n.parent; - while (topLevelNode.parent !== undefined) { - topLevelNode = topLevelNode.parent; - } - - n.kx = topLevelNode.x; - n.ky = topLevelNode.y; + if (n.parent !== undefined) { + // Is a grouped node - inherit parent's position so edges point into parent + // d3 thinks it has moved it to x and y but we have final say using kx and ky. + let topLevelNode = n.parent; + while (topLevelNode.parent !== undefined) { + topLevelNode = topLevelNode.parent; } - }); - } - if (self.changeHandler) { - // Hook to allow any client to respond to position changes - // e.g. angular adjusts and repaints node positions on screen. - self.changeHandler(); - } - }); - this.force.start(); - }; - //========Grouping functions========== - - //Merges all selected nodes into node - this.groupSelections = function(node) { - const ops = []; - self.nodes.forEach(function(otherNode) { - if (otherNode !== node && otherNode.isSelected && otherNode.parent === undefined) { - otherNode.parent = node; - otherNode.isSelected = false; - self.arrRemove(self.selectedNodes, otherNode); - ops.push(new GroupOperation(node, otherNode)); + n.kx = topLevelNode.x; + n.ky = topLevelNode.y; + } + }); } - }); - self.selectNone(); - self.selectNode(node); - self.addUndoLogEntry(ops); - self.runLayout(); - }; - - this.mergeNeighbours = function(node) { - const neighbours = self.getNeighbours(node); - const ops = []; - neighbours.forEach(function(otherNode) { - if (otherNode !== node && otherNode.parent === undefined) { - otherNode.parent = node; - otherNode.isSelected = false; - self.arrRemove(self.selectedNodes, otherNode); - ops.push(new GroupOperation(node, otherNode)); + if (self.changeHandler) { + // Hook to allow any client to respond to position changes + // e.g. angular adjusts and repaints node positions on screen. + self.changeHandler(); } }); - self.addUndoLogEntry(ops); - self.runLayout(); - }; + this.force.start(); + }; - this.mergeSelections = function(targetNode) { - if (!targetNode) { - console.log('Error - merge called on undefined target'); - return; + //========Grouping functions========== + + //Merges all selected nodes into node + this.groupSelections = function(node) { + const ops = []; + self.nodes.forEach(function(otherNode) { + if (otherNode !== node && otherNode.isSelected && otherNode.parent === undefined) { + otherNode.parent = node; + otherNode.isSelected = false; + self.arrRemove(self.selectedNodes, otherNode); + ops.push(new GroupOperation(node, otherNode)); } - const selClone = self.selectedNodes.slice(); - const ops = []; - selClone.forEach(function(otherNode) { - if (otherNode !== targetNode && otherNode.parent === undefined) { - otherNode.parent = targetNode; - otherNode.isSelected = false; - self.arrRemove(self.selectedNodes, otherNode); - ops.push(new GroupOperation(targetNode, otherNode)); - } - }); - self.addUndoLogEntry(ops); - self.runLayout(); - }; - - this.ungroup = function(node) { - const ops = []; - self.nodes.forEach(function(other) { - if (other.parent === node) { - other.parent = undefined; - ops.push(new UnGroupOperation(node, other)); - } - }); - self.addUndoLogEntry(ops); - self.runLayout(); - }; - - this.unblacklist = function(node) { - self.arrRemove(self.blacklistedNodes, node); - }; - - this.blacklistSelection = function() { - const selection = self.getAllSelectedNodes(); - const danglingEdges = []; - self.edges.forEach(function(edge) { - if (selection.indexOf(edge.source) >= 0 || selection.indexOf(edge.target) >= 0) { - delete self.edgesMap[edge.id]; - danglingEdges.push(edge); - } - }); - selection.forEach(node => { - delete self.nodesMap[node.id]; - self.blacklistedNodes.push(node); - node.isSelected = false; - }); - self.arrRemoveAll(self.nodes, selection); - self.arrRemoveAll(self.edges, danglingEdges); - self.selectedNodes = []; - self.runLayout(); - }; - - // A "simple search" operation that requires no parameters from the client. - // Performs numHops hops pulling in field-specific number of terms each time - this.simpleSearch = function(searchTerm, fieldsChoice, numHops) { - const qs = { - query_string: { - query: searchTerm, - }, - }; - return this.search(qs, fieldsChoice, numHops); - }; + }); + self.selectNone(); + self.selectNode(node); + self.addUndoLogEntry(ops); + self.runLayout(); + }; - this.search = function(query, fieldsChoice, numHops) { - if (!fieldsChoice) { - fieldsChoice = self.options.vertex_fields; + this.mergeNeighbours = function(node) { + const neighbours = self.getNeighbours(node); + const ops = []; + neighbours.forEach(function(otherNode) { + if (otherNode !== node && otherNode.parent === undefined) { + otherNode.parent = node; + otherNode.isSelected = false; + self.arrRemove(self.selectedNodes, otherNode); + ops.push(new GroupOperation(node, otherNode)); } - let step = {}; - - //Add any blacklisted nodes to exclusion list - const excludeNodesByField = {}; - const nots = []; - const avoidNodes = this.blacklistedNodes; - for (let i = 0; i < avoidNodes.length; i++) { - const n = avoidNodes[i]; - let arr = excludeNodesByField[n.data.field]; - if (!arr) { - arr = []; - excludeNodesByField[n.data.field] = arr; - } - arr.push(n.data.term); - //Add to list of must_nots in guiding query - const tq = {}; - tq[n.data.field] = n.data.term; - nots.push({ - term: tq, - }); - } - - const rootStep = step; - for (let hopNum = 0; hopNum < numHops; hopNum++) { - const arr = []; + }); + self.addUndoLogEntry(ops); + self.runLayout(); + }; - fieldsChoice.forEach(({ name: field, hopSize }) => { - const excludes = excludeNodesByField[field]; - const stepField = { - field: field, - size: hopSize, - min_doc_count: parseInt(self.options.exploreControls.minDocCount), - }; - if (excludes) { - stepField.exclude = excludes; - } - arr.push(stepField); - }); - step.vertices = arr; - if (hopNum < numHops - 1) { - // if (s < (stepSizes.length - 1)) { - const nextStep = {}; - step.connections = nextStep; - step = nextStep; - } + this.mergeSelections = function(targetNode) { + if (!targetNode) { + console.log('Error - merge called on undefined target'); + return; + } + const selClone = self.selectedNodes.slice(); + const ops = []; + selClone.forEach(function(otherNode) { + if (otherNode !== targetNode && otherNode.parent === undefined) { + otherNode.parent = targetNode; + otherNode.isSelected = false; + self.arrRemove(self.selectedNodes, otherNode); + ops.push(new GroupOperation(targetNode, otherNode)); } + }); + self.addUndoLogEntry(ops); + self.runLayout(); + }; - if (nots.length > 0) { - query = { - bool: { - must: [query], - must_not: nots, - }, - }; + this.ungroup = function(node) { + const ops = []; + self.nodes.forEach(function(other) { + if (other.parent === node) { + other.parent = undefined; + ops.push(new UnGroupOperation(node, other)); } + }); + self.addUndoLogEntry(ops); + self.runLayout(); + }; - const request = { - query: query, - controls: self.buildControls(), - connections: rootStep.connections, - vertices: rootStep.vertices, - }; - self.callElasticsearch(request); - }; - - this.buildControls = function() { - //This is an object managed by the client that may be subject to change - const guiSettingsObj = self.options.exploreControls; + this.unblacklist = function(node) { + self.arrRemove(self.blacklistedNodes, node); + }; - const controls = { - use_significance: guiSettingsObj.useSignificance, - sample_size: guiSettingsObj.sampleSize, - timeout: parseInt(guiSettingsObj.timeoutMillis), - }; - // console.log("guiSettingsObj",guiSettingsObj); - if (guiSettingsObj.sampleDiversityField != null) { - controls.sample_diversity = { - field: guiSettingsObj.sampleDiversityField.name, - max_docs_per_value: guiSettingsObj.maxValuesPerDoc, - }; + this.blacklistSelection = function() { + const selection = self.getAllSelectedNodes(); + const danglingEdges = []; + self.edges.forEach(function(edge) { + if (selection.indexOf(edge.source) >= 0 || selection.indexOf(edge.target) >= 0) { + delete self.edgesMap[edge.id]; + danglingEdges.push(edge); } - return controls; - }; + }); + selection.forEach(node => { + delete self.nodesMap[node.id]; + self.blacklistedNodes.push(node); + node.isSelected = false; + }); + self.arrRemoveAll(self.nodes, selection); + self.arrRemoveAll(self.edges, danglingEdges); + self.selectedNodes = []; + self.runLayout(); + }; - this.makeNodeId = function(field, term) { - return field + '..' + term; + // A "simple search" operation that requires no parameters from the client. + // Performs numHops hops pulling in field-specific number of terms each time + this.simpleSearch = function(searchTerm, fieldsChoice, numHops) { + const qs = { + query_string: { + query: searchTerm, + }, }; + return this.search(qs, fieldsChoice, numHops); + }; - this.makeEdgeId = function(srcId, targetId) { - let id = srcId + '->' + targetId; - if (srcId > targetId) { - id = targetId + '->' + srcId; + this.search = function(query, fieldsChoice, numHops) { + if (!fieldsChoice) { + fieldsChoice = self.options.vertex_fields; + } + let step = {}; + + //Add any blacklisted nodes to exclusion list + const excludeNodesByField = {}; + const nots = []; + const avoidNodes = this.blacklistedNodes; + for (let i = 0; i < avoidNodes.length; i++) { + const n = avoidNodes[i]; + let arr = excludeNodesByField[n.data.field]; + if (!arr) { + arr = []; + excludeNodesByField[n.data.field] = arr; } - return id; - }; + arr.push(n.data.term); + //Add to list of must_nots in guiding query + const tq = {}; + tq[n.data.field] = n.data.term; + nots.push({ + term: tq, + }); + } - //======= Adds new nodes retrieved from an elasticsearch search ======== - this.mergeGraph = function(newData) { - this.stopLayout(); + const rootStep = step; + for (let hopNum = 0; hopNum < numHops; hopNum++) { + const arr = []; - if (!newData.nodes) { - newData.nodes = []; - } - const lastOps = []; - - // === Commented out - not sure it was obvious to users what various circle sizes meant - // var minCircleSize = 5; - // var maxCircleSize = 25; - // var sizeScale = d3.scale.pow().exponent(0.15) - // .domain([0, d3.max(newData.nodes, function(d) { - // return d.weight; - // })]) - // .range([minCircleSize, maxCircleSize]); - - //Remove nodes we already have - const dedupedNodes = []; - newData.nodes.forEach(node => { - //Assign an ID - node.id = self.makeNodeId(node.field, node.term); - if (!this.nodesMap[node.id]) { - //Default the label - if (!node.label) { - node.label = node.term; - } - dedupedNodes.push(node); + fieldsChoice.forEach(({ name: field, hopSize }) => { + const excludes = excludeNodesByField[field]; + const stepField = { + field: field, + size: hopSize, + min_doc_count: parseInt(self.options.exploreControls.minDocCount), + }; + if (excludes) { + stepField.exclude = excludes; } + arr.push(stepField); }); - if (dedupedNodes.length > 0 && this.options.nodeLabeller) { - // A hook for client code to attach labels etc to newly introduced nodes. - this.options.nodeLabeller(dedupedNodes); + step.vertices = arr; + if (hopNum < numHops - 1) { + // if (s < (stepSizes.length - 1)) { + const nextStep = {}; + step.connections = nextStep; + step = nextStep; } + } - dedupedNodes.forEach(dedupedNode => { - let label = dedupedNode.term; - if (dedupedNode.label) { - label = dedupedNode.label; - } + if (nots.length > 0) { + query = { + bool: { + must: [query], + must_not: nots, + }, + }; + } - const node = { - x: 1, - y: 1, - numChildren: 0, - parent: undefined, - isSelected: false, - id: dedupedNode.id, - label: label, - color: dedupedNode.color, - icon: dedupedNode.icon, - data: dedupedNode, - }; - // node.scaledSize = sizeScale(node.data.weight); - node.scaledSize = 15; - node.seqNumber = this.seqNumber++; - this.nodes.push(node); - lastOps.push(new AddNodeOperation(node, self)); - this.nodesMap[node.id] = node; - }); + const request = { + query: query, + controls: self.buildControls(), + connections: rootStep.connections, + vertices: rootStep.vertices, + }; + self.callElasticsearch(request); + }; - newData.edges.forEach(edge => { - const src = newData.nodes[edge.source]; - const target = newData.nodes[edge.target]; - edge.id = this.makeEdgeId(src.id, target.id); + this.buildControls = function() { + //This is an object managed by the client that may be subject to change + const guiSettingsObj = self.options.exploreControls; - //Lookup the wrappers object that will hold display Info like x/y coordinates - const srcWrapperObj = this.nodesMap[src.id]; - const targetWrapperObj = this.nodesMap[target.id]; + const controls = { + use_significance: guiSettingsObj.useSignificance, + sample_size: guiSettingsObj.sampleSize, + timeout: parseInt(guiSettingsObj.timeoutMillis), + }; + // console.log("guiSettingsObj",guiSettingsObj); + if (guiSettingsObj.sampleDiversityField != null) { + controls.sample_diversity = { + field: guiSettingsObj.sampleDiversityField.name, + max_docs_per_value: guiSettingsObj.maxValuesPerDoc, + }; + } + return controls; + }; - const existingEdge = this.edgesMap[edge.id]; - if (existingEdge) { - existingEdge.weight = Math.max(existingEdge.weight, edge.weight); - //TODO update width too? - existingEdge.doc_count = Math.max(existingEdge.doc_count, edge.doc_count); - return; - } - const newEdge = { - source: srcWrapperObj, - target: targetWrapperObj, - weight: edge.weight, - width: edge.width, - id: edge.id, - doc_count: edge.doc_count, - }; - if (edge.label) { - newEdge.label = edge.label; - } + this.makeNodeId = function(field, term) { + return field + '..' + term; + }; - this.edgesMap[newEdge.id] = newEdge; - this.edges.push(newEdge); - lastOps.push(new AddEdgeOperation(newEdge, self)); - }); + this.makeEdgeId = function(srcId, targetId) { + let id = srcId + '->' + targetId; + if (srcId > targetId) { + id = targetId + '->' + srcId; + } + return id; + }; + + //======= Adds new nodes retrieved from an elasticsearch search ======== + this.mergeGraph = function(newData) { + this.stopLayout(); + + if (!newData.nodes) { + newData.nodes = []; + } + const lastOps = []; + + // === Commented out - not sure it was obvious to users what various circle sizes meant + // var minCircleSize = 5; + // var maxCircleSize = 25; + // var sizeScale = d3.scale.pow().exponent(0.15) + // .domain([0, d3.max(newData.nodes, function(d) { + // return d.weight; + // })]) + // .range([minCircleSize, maxCircleSize]); + + //Remove nodes we already have + const dedupedNodes = []; + newData.nodes.forEach(node => { + //Assign an ID + node.id = self.makeNodeId(node.field, node.term); + if (!this.nodesMap[node.id]) { + //Default the label + if (!node.label) { + node.label = node.term; + } + dedupedNodes.push(node); + } + }); + if (dedupedNodes.length > 0 && this.options.nodeLabeller) { + // A hook for client code to attach labels etc to newly introduced nodes. + this.options.nodeLabeller(dedupedNodes); + } - if (lastOps.length > 0) { - self.addUndoLogEntry(lastOps); + dedupedNodes.forEach(dedupedNode => { + let label = dedupedNode.term; + if (dedupedNode.label) { + label = dedupedNode.label; } - this.runLayout(); - }; + const node = { + x: 1, + y: 1, + numChildren: 0, + parent: undefined, + isSelected: false, + id: dedupedNode.id, + label: label, + color: dedupedNode.color, + icon: dedupedNode.icon, + data: dedupedNode, + }; + // node.scaledSize = sizeScale(node.data.weight); + node.scaledSize = 15; + node.seqNumber = this.seqNumber++; + this.nodes.push(node); + lastOps.push(new AddNodeOperation(node, self)); + this.nodesMap[node.id] = node; + }); - this.mergeIds = function(parentId, childId) { - const parent = self.getNode(parentId); - const child = self.getNode(childId); - if (child.isSelected) { - child.isSelected = false; - self.arrRemove(self.selectedNodes, child); + newData.edges.forEach(edge => { + const src = newData.nodes[edge.source]; + const target = newData.nodes[edge.target]; + edge.id = this.makeEdgeId(src.id, target.id); + + //Lookup the wrappers object that will hold display Info like x/y coordinates + const srcWrapperObj = this.nodesMap[src.id]; + const targetWrapperObj = this.nodesMap[target.id]; + + const existingEdge = this.edgesMap[edge.id]; + if (existingEdge) { + existingEdge.weight = Math.max(existingEdge.weight, edge.weight); + //TODO update width too? + existingEdge.doc_count = Math.max(existingEdge.doc_count, edge.doc_count); + return; + } + const newEdge = { + source: srcWrapperObj, + target: targetWrapperObj, + weight: edge.weight, + width: edge.width, + id: edge.id, + doc_count: edge.doc_count, + }; + if (edge.label) { + newEdge.label = edge.label; } - child.parent = parent; - self.addUndoLogEntry([new GroupOperation(parent, child)]); - self.runLayout(); - }; - this.getNode = function(nodeId) { - return this.nodesMap[nodeId]; - }; - this.getEdge = function(edgeId) { - return this.edgesMap[edgeId]; - }; + this.edgesMap[newEdge.id] = newEdge; + this.edges.push(newEdge); + lastOps.push(new AddEdgeOperation(newEdge, self)); + }); - //======= Expand functions to request new additions to the graph + if (lastOps.length > 0) { + self.addUndoLogEntry(lastOps); + } - this.expandSelecteds = function(targetOptions = {}) { - let startNodes = self.getAllSelectedNodes(); - if (startNodes.length === 0) { - startNodes = self.nodes; - } - const clone = startNodes.slice(); - self.expand(clone, targetOptions); - }; + this.runLayout(); + }; - this.expandGraph = function() { - self.expandSelecteds(); - }; + this.mergeIds = function(parentId, childId) { + const parent = self.getNode(parentId); + const child = self.getNode(childId); + if (child.isSelected) { + child.isSelected = false; + self.arrRemove(self.selectedNodes, child); + } + child.parent = parent; + self.addUndoLogEntry([new GroupOperation(parent, child)]); + self.runLayout(); + }; - //Find new nodes to link to existing selected nodes - this.expandNode = function(node) { - self.expand(self.returnUnpackedGroupeds([node]), {}); - }; + this.getNode = function(nodeId) { + return this.nodesMap[nodeId]; + }; + this.getEdge = function(edgeId) { + return this.edgesMap[edgeId]; + }; - // A manual expand function where the client provides the list - // of existing nodes that are the start points and some options - // about what targets are of interest. - this.expand = function(startNodes, targetOptions) { - //============================= - const nodesByField = {}; - const excludeNodesByField = {}; - - //Add any blacklisted nodes to exclusion list - const avoidNodes = this.blacklistedNodes; - for (let i = 0; i < avoidNodes.length; i++) { - const n = avoidNodes[i]; - let arr = excludeNodesByField[n.data.field]; - if (!arr) { - arr = []; - excludeNodesByField[n.data.field] = arr; - } - if (arr.indexOf(n.data.term) < 0) { - arr.push(n.data.term); - } - } + //======= Expand functions to request new additions to the graph - const allExistingNodes = this.nodes; - for (let i = 0; i < allExistingNodes.length; i++) { - const n = allExistingNodes[i]; - let arr = excludeNodesByField[n.data.field]; - if (!arr) { - arr = []; - excludeNodesByField[n.data.field] = arr; - } - arr.push(n.data.term); - } + this.expandSelecteds = function(targetOptions = {}) { + let startNodes = self.getAllSelectedNodes(); + if (startNodes.length === 0) { + startNodes = self.nodes; + } + const clone = startNodes.slice(); + self.expand(clone, targetOptions); + }; - //Organize nodes by field - for (let i = 0; i < startNodes.length; i++) { - const n = startNodes[i]; - let arr = nodesByField[n.data.field]; - if (!arr) { - arr = []; - nodesByField[n.data.field] = arr; - } - // pushing boosts server-side to influence sampling/direction - arr.push({ - term: n.data.term, - boost: n.data.weight, - }); + this.expandGraph = function() { + self.expandSelecteds(); + }; - arr = excludeNodesByField[n.data.field]; - if (!arr) { - arr = []; - excludeNodesByField[n.data.field] = arr; - } - //NOTE for the entity-building use case need to remove excludes that otherwise - // prevent bridge-building. - if (arr.indexOf(n.data.term) < 0) { - arr.push(n.data.term); - } + //Find new nodes to link to existing selected nodes + this.expandNode = function(node) { + self.expand(self.returnUnpackedGroupeds([node]), {}); + }; + + // A manual expand function where the client provides the list + // of existing nodes that are the start points and some options + // about what targets are of interest. + this.expand = function(startNodes, targetOptions) { + //============================= + const nodesByField = {}; + const excludeNodesByField = {}; + + //Add any blacklisted nodes to exclusion list + const avoidNodes = this.blacklistedNodes; + for (let i = 0; i < avoidNodes.length; i++) { + const n = avoidNodes[i]; + let arr = excludeNodesByField[n.data.field]; + if (!arr) { + arr = []; + excludeNodesByField[n.data.field] = arr; } + if (arr.indexOf(n.data.term) < 0) { + arr.push(n.data.term); + } + } - const primaryVertices = []; - const secondaryVertices = []; - for (const fieldName in nodesByField) { - if (nodesByField.hasOwnProperty(fieldName)) { - primaryVertices.push({ - field: fieldName, - include: nodesByField[fieldName], - min_doc_count: parseInt(self.options.exploreControls.minDocCount), - }); - } + const allExistingNodes = this.nodes; + for (let i = 0; i < allExistingNodes.length; i++) { + const n = allExistingNodes[i]; + let arr = excludeNodesByField[n.data.field]; + if (!arr) { + arr = []; + excludeNodesByField[n.data.field] = arr; } + arr.push(n.data.term); + } - let targetFields = this.options.vertex_fields; - if (targetOptions.toFields) { - targetFields = targetOptions.toFields; + //Organize nodes by field + for (let i = 0; i < startNodes.length; i++) { + const n = startNodes[i]; + let arr = nodesByField[n.data.field]; + if (!arr) { + arr = []; + nodesByField[n.data.field] = arr; } + // pushing boosts server-side to influence sampling/direction + arr.push({ + term: n.data.term, + boost: n.data.weight, + }); - //Identify target fields - targetFields.forEach(targetField => { - const fieldName = targetField.name; - // Sometimes the target field is disabled from loading new hops so we need to use the last valid figure - const hopSize = - targetField.hopSize > 0 ? targetField.hopSize : targetField.lastValidHopSize; + arr = excludeNodesByField[n.data.field]; + if (!arr) { + arr = []; + excludeNodesByField[n.data.field] = arr; + } + //NOTE for the entity-building use case need to remove excludes that otherwise + // prevent bridge-building. + if (arr.indexOf(n.data.term) < 0) { + arr.push(n.data.term); + } + } - const fieldHop = { + const primaryVertices = []; + const secondaryVertices = []; + for (const fieldName in nodesByField) { + if (nodesByField.hasOwnProperty(fieldName)) { + primaryVertices.push({ field: fieldName, - size: hopSize, + include: nodesByField[fieldName], min_doc_count: parseInt(self.options.exploreControls.minDocCount), - }; - fieldHop.exclude = excludeNodesByField[fieldName]; - secondaryVertices.push(fieldHop); - }); + }); + } + } - const request = { - controls: self.buildControls(), - vertices: primaryVertices, - connections: { - vertices: secondaryVertices, - }, + let targetFields = this.options.vertex_fields; + if (targetOptions.toFields) { + targetFields = targetOptions.toFields; + } + + //Identify target fields + targetFields.forEach(targetField => { + const fieldName = targetField.name; + // Sometimes the target field is disabled from loading new hops so we need to use the last valid figure + const hopSize = targetField.hopSize > 0 ? targetField.hopSize : targetField.lastValidHopSize; + + const fieldHop = { + field: fieldName, + size: hopSize, + min_doc_count: parseInt(self.options.exploreControls.minDocCount), }; - self.lastRequest = JSON.stringify(request, null, '\t'); - graphExplorer(self.options.indexName, request, function(data) { - self.lastResponse = JSON.stringify(data, null, '\t'); - const edges = []; - - //Label fields with a field number for CSS styling - data.vertices.forEach(node => { - targetFields.some(fieldDef => { - if (node.field === fieldDef.name) { - node.color = fieldDef.color; - node.icon = fieldDef.icon; - node.fieldDef = fieldDef; - return true; - } - return false; - }); - }); + fieldHop.exclude = excludeNodesByField[fieldName]; + secondaryVertices.push(fieldHop); + }); - // Size the edges based on the maximum weight - const minLineSize = 2; - const maxLineSize = 10; - let maxEdgeWeight = 0.00000001; - data.connections.forEach(edge => { - maxEdgeWeight = Math.max(maxEdgeWeight, edge.weight); - edges.push({ - source: edge.source, - target: edge.target, - doc_count: edge.doc_count, - weight: edge.weight, - width: Math.max(minLineSize, (edge.weight / maxEdgeWeight) * maxLineSize), - }); + const request = { + controls: self.buildControls(), + vertices: primaryVertices, + connections: { + vertices: secondaryVertices, + }, + }; + self.lastRequest = JSON.stringify(request, null, '\t'); + graphExplorer(self.options.indexName, request, function(data) { + self.lastResponse = JSON.stringify(data, null, '\t'); + const edges = []; + + //Label fields with a field number for CSS styling + data.vertices.forEach(node => { + targetFields.some(fieldDef => { + if (node.field === fieldDef.name) { + node.color = fieldDef.color; + node.icon = fieldDef.icon; + node.fieldDef = fieldDef; + return true; + } + return false; }); + }); - // Add the new nodes and edges into the existing workspace's graph - self.mergeGraph({ - nodes: data.vertices, - edges: edges, + // Size the edges based on the maximum weight + const minLineSize = 2; + const maxLineSize = 10; + let maxEdgeWeight = 0.00000001; + data.connections.forEach(edge => { + maxEdgeWeight = Math.max(maxEdgeWeight, edge.weight); + edges.push({ + source: edge.source, + target: edge.target, + doc_count: edge.doc_count, + weight: edge.weight, + width: Math.max(minLineSize, (edge.weight / maxEdgeWeight) * maxLineSize), }); }); - //===== End expand graph ======================== - }; - this.trimExcessNewEdges = function(newNodes, newEdges) { - let trimmedEdges = []; - const maxNumEdgesToReturn = 5; - //Trim here to just the new edges that are most interesting. - newEdges.forEach(edge => { - const src = newNodes[edge.source]; - const target = newNodes[edge.target]; - const srcId = src.field + '..' + src.term; - const targetId = target.field + '..' + target.term; - const id = this.makeEdgeId(srcId, targetId); - const existingSrcNode = self.nodesMap[srcId]; - const existingTargetNode = self.nodesMap[targetId]; - if (existingSrcNode != null && existingTargetNode != null) { - if (existingSrcNode.parent !== undefined && existingTargetNode.parent !== undefined) { - // both nodes are rolled-up and grouped so this edge would not be a visible - // change to the graph - lose it in favour of any other visible ones. - return; - } - } else { - console.log('Error? Missing nodes ' + srcId + ' or ' + targetId, self.nodesMap); - return; - } + // Add the new nodes and edges into the existing workspace's graph + self.mergeGraph({ + nodes: data.vertices, + edges: edges, + }); + }); + //===== End expand graph ======================== + }; - const existingEdge = self.edgesMap[id]; - if (existingEdge) { - existingEdge.weight = Math.max(existingEdge.weight, edge.weight); - existingEdge.doc_count = Math.max(existingEdge.doc_count, edge.doc_count); + this.trimExcessNewEdges = function(newNodes, newEdges) { + let trimmedEdges = []; + const maxNumEdgesToReturn = 5; + //Trim here to just the new edges that are most interesting. + newEdges.forEach(edge => { + const src = newNodes[edge.source]; + const target = newNodes[edge.target]; + const srcId = src.field + '..' + src.term; + const targetId = target.field + '..' + target.term; + const id = this.makeEdgeId(srcId, targetId); + const existingSrcNode = self.nodesMap[srcId]; + const existingTargetNode = self.nodesMap[targetId]; + if (existingSrcNode != null && existingTargetNode != null) { + if (existingSrcNode.parent !== undefined && existingTargetNode.parent !== undefined) { + // both nodes are rolled-up and grouped so this edge would not be a visible + // change to the graph - lose it in favour of any other visible ones. return; - } else { - trimmedEdges.push(edge); } - }); - if (trimmedEdges.length > maxNumEdgesToReturn) { - //trim to only the most interesting ones - trimmedEdges.sort(function(a, b) { - return b.weight - a.weight; - }); - trimmedEdges = trimmedEdges.splice(0, maxNumEdgesToReturn); + } else { + console.log('Error? Missing nodes ' + srcId + ' or ' + targetId, self.nodesMap); + return; } - return trimmedEdges; - }; - this.getQuery = function(startNodes, loose) { - const shoulds = []; - let nodes = startNodes; - if (!startNodes) { - nodes = self.nodes; + const existingEdge = self.edgesMap[id]; + if (existingEdge) { + existingEdge.weight = Math.max(existingEdge.weight, edge.weight); + existingEdge.doc_count = Math.max(existingEdge.doc_count, edge.doc_count); + return; + } else { + trimmedEdges.push(edge); } - nodes.forEach(node => { - if (node.parent === undefined) { - shoulds.push(self.buildNodeQuery(node)); - } + }); + if (trimmedEdges.length > maxNumEdgesToReturn) { + //trim to only the most interesting ones + trimmedEdges.sort(function(a, b) { + return b.weight - a.weight; }); - return { - bool: { - should: shoulds, - minimum_should_match: Math.min(shoulds.length, loose ? 1 : 2), - }, - }; - }; + trimmedEdges = trimmedEdges.splice(0, maxNumEdgesToReturn); + } + return trimmedEdges; + }; - this.getSelectedOrAllNodes = function() { - let startNodes = self.getAllSelectedNodes(); - if (startNodes.length === 0) { - startNodes = self.nodes; + this.getQuery = function(startNodes, loose) { + const shoulds = []; + let nodes = startNodes; + if (!startNodes) { + nodes = self.nodes; + } + nodes.forEach(node => { + if (node.parent === undefined) { + shoulds.push(self.buildNodeQuery(node)); } - return startNodes; + }); + return { + bool: { + should: shoulds, + minimum_should_match: Math.min(shoulds.length, loose ? 1 : 2), + }, }; + }; - this.getSelectedOrAllTopNodes = function() { - return self.getSelectedOrAllNodes().filter(function(node) { - return node.parent === undefined; - }); - }; + this.getSelectedOrAllNodes = function() { + let startNodes = self.getAllSelectedNodes(); + if (startNodes.length === 0) { + startNodes = self.nodes; + } + return startNodes; + }; - function addTermToFieldList(map, field, term) { - let arr = map[field]; - if (!arr) { - arr = []; - map[field] = arr; - } - arr.push(term); + this.getSelectedOrAllTopNodes = function() { + return self.getSelectedOrAllNodes().filter(function(node) { + return node.parent === undefined; + }); + }; + + function addTermToFieldList(map, field, term) { + let arr = map[field]; + if (!arr) { + arr = []; + map[field] = arr; } + arr.push(term); + } - /** - * Add missing links between existing nodes - * @param maxNewEdges Max number of new edges added. Avoid adding too many new edges - * at once into the graph otherwise disorientating - */ - this.fillInGraph = function(maxNewEdges = 10) { - let nodesForLinking = self.getSelectedOrAllTopNodes(); - - const maxNumVerticesSearchable = 100; - - // Server limitation - we can only search for connections between max 100 vertices at a time. - if (nodesForLinking.length > maxNumVerticesSearchable) { - //Make a selection of random nodes from the array. Shift the random choices - // to the front of the array. - for (let i = 0; i < maxNumVerticesSearchable; i++) { - const oldNode = nodesForLinking[i]; - const randomIndex = Math.floor(Math.random() * (nodesForLinking.length - i)) + i; - //Swap the node positions of the randomly selected node and i - nodesForLinking[i] = nodesForLinking[randomIndex]; - nodesForLinking[randomIndex] = oldNode; - } - // Trim to our random selection - nodesForLinking = nodesForLinking.slice(0, maxNumVerticesSearchable - 1); + /** + * Add missing links between existing nodes + * @param maxNewEdges Max number of new edges added. Avoid adding too many new edges + * at once into the graph otherwise disorientating + */ + this.fillInGraph = function(maxNewEdges = 10) { + let nodesForLinking = self.getSelectedOrAllTopNodes(); + + const maxNumVerticesSearchable = 100; + + // Server limitation - we can only search for connections between max 100 vertices at a time. + if (nodesForLinking.length > maxNumVerticesSearchable) { + //Make a selection of random nodes from the array. Shift the random choices + // to the front of the array. + for (let i = 0; i < maxNumVerticesSearchable; i++) { + const oldNode = nodesForLinking[i]; + const randomIndex = Math.floor(Math.random() * (nodesForLinking.length - i)) + i; + //Swap the node positions of the randomly selected node and i + nodesForLinking[i] = nodesForLinking[randomIndex]; + nodesForLinking[randomIndex] = oldNode; } + // Trim to our random selection + nodesForLinking = nodesForLinking.slice(0, maxNumVerticesSearchable - 1); + } - // Create our query/aggregation request using the selected nodes. - // Filters are named after the index of the node in the nodesForLinking - // array. The result bucket describing the relationship between - // the first 2 nodes in the array will therefore be labelled "0|1" - const shoulds = []; - const filterMap = {}; - nodesForLinking.forEach(function(node, nodeNum) { - const nodeQuery = self.buildNodeQuery(node); - shoulds.push(nodeQuery); - filterMap[nodeNum] = nodeQuery; - }); - const searchReq = { - size: 0, - query: { - bool: { - // Only match docs that share 2 nodes so can help describe their relationship - minimum_should_match: 2, - should: shoulds, - }, + // Create our query/aggregation request using the selected nodes. + // Filters are named after the index of the node in the nodesForLinking + // array. The result bucket describing the relationship between + // the first 2 nodes in the array will therefore be labelled "0|1" + const shoulds = []; + const filterMap = {}; + nodesForLinking.forEach(function(node, nodeNum) { + const nodeQuery = self.buildNodeQuery(node); + shoulds.push(nodeQuery); + filterMap[nodeNum] = nodeQuery; + }); + const searchReq = { + size: 0, + query: { + bool: { + // Only match docs that share 2 nodes so can help describe their relationship + minimum_should_match: 2, + should: shoulds, }, - aggs: { - matrix: { - adjacency_matrix: { - separator: '|', - filters: filterMap, - }, + }, + aggs: { + matrix: { + adjacency_matrix: { + separator: '|', + filters: filterMap, }, }, - }; + }, + }; - // Search for connections between the selected nodes. - searcher(self.options.indexName, searchReq, function(data) { - const numDocsMatched = data.hits.total; - const buckets = data.aggregations.matrix.buckets; - const vertices = nodesForLinking.map(function(existingNode) { - return { - field: existingNode.data.field, - term: existingNode.data.term, - weight: 1, - depth: 0, - }; - }); + // Search for connections between the selected nodes. + searcher(self.options.indexName, searchReq, function(data) { + const numDocsMatched = data.hits.total; + const buckets = data.aggregations.matrix.buckets; + const vertices = nodesForLinking.map(function(existingNode) { + return { + field: existingNode.data.field, + term: existingNode.data.term, + weight: 1, + depth: 0, + }; + }); - let connections = []; - let maxEdgeWeight = 0; - // Turn matrix array of results into a map - const keyedBuckets = {}; - buckets.forEach(function(bucket) { - keyedBuckets[bucket.key] = bucket; - }); + let connections = []; + let maxEdgeWeight = 0; + // Turn matrix array of results into a map + const keyedBuckets = {}; + buckets.forEach(function(bucket) { + keyedBuckets[bucket.key] = bucket; + }); - buckets.forEach(function(bucket) { - // We calibrate line thickness based on % of max weight of - // all edges (including the edges we may already have in the workspace) - const ids = bucket.key.split('|'); - if (ids.length === 2) { - // bucket represents an edge - if (self.options.exploreControls.useSignificance) { - const t1 = keyedBuckets[ids[0]].doc_count; - const t2 = keyedBuckets[ids[1]].doc_count; - const t1AndT2 = bucket.doc_count; - // Calc the significant_terms score to prioritize selection of interesting links - bucket.weight = self.jLHScore( - t1AndT2, - Math.max(t1, t2), - Math.min(t1, t2), - numDocsMatched - ); - } else { - // prioritize links purely on volume of intersecting docs - bucket.weight = bucket.doc_count; - } - maxEdgeWeight = Math.max(maxEdgeWeight, bucket.weight); - } - }); - const backFilledMinLineSize = 2; - const backFilledMaxLineSize = 5; - buckets.forEach(function(bucket) { - if (bucket.doc_count < parseInt(self.options.exploreControls.minDocCount)) { - return; - } - const ids = bucket.key.split('|'); - if (ids.length === 2) { - // Bucket represents an edge - const srcNode = nodesForLinking[ids[0]]; - const targetNode = nodesForLinking[ids[1]]; - const edgeId = self.makeEdgeId(srcNode.id, targetNode.id); - const existingEdge = self.edgesMap[edgeId]; - if (existingEdge) { - // Tweak the doc_count score having just looked it up. - existingEdge.doc_count = Math.max(existingEdge.doc_count, bucket.doc_count); - } else { - connections.push({ - // source and target values are indexes into the vertices array - source: parseInt(ids[0]), - target: parseInt(ids[1]), - weight: bucket.weight, - width: Math.max( - backFilledMinLineSize, - (bucket.weight / maxEdgeWeight) * backFilledMaxLineSize - ), - doc_count: bucket.doc_count, - }); - } + buckets.forEach(function(bucket) { + // We calibrate line thickness based on % of max weight of + // all edges (including the edges we may already have in the workspace) + const ids = bucket.key.split('|'); + if (ids.length === 2) { + // bucket represents an edge + if (self.options.exploreControls.useSignificance) { + const t1 = keyedBuckets[ids[0]].doc_count; + const t2 = keyedBuckets[ids[1]].doc_count; + const t1AndT2 = bucket.doc_count; + // Calc the significant_terms score to prioritize selection of interesting links + bucket.weight = self.jLHScore( + t1AndT2, + Math.max(t1, t2), + Math.min(t1, t2), + numDocsMatched + ); + } else { + // prioritize links purely on volume of intersecting docs + bucket.weight = bucket.doc_count; } - }); - // Trim the array of connections so that we don't add too many at once - disorientating for users otherwise - if (connections.length > maxNewEdges) { - connections = connections.sort(function(a, b) { - return b.weight - a.weight; - }); - connections = connections.slice(0, maxNewEdges); + maxEdgeWeight = Math.max(maxEdgeWeight, bucket.weight); } - - // Merge the new edges into the existing workspace's graph. - // We reuse the mergeGraph function used to handle the - // results of other calls to the server-side Graph API - // so must package the results here with that same format - // even though we know all the vertices we provide will - // be duplicates and ignored. - self.mergeGraph({ - nodes: vertices, - edges: connections, - }); }); - }; - - // Provide a "fuzzy find similar" query that can find similar docs but preferably - // not re-iterating the exact terms we already have in the workspace. - // We use a free-text search on the index's configured default field (typically '_all') - // to drill-down into docs that should be linked but aren't via the exact terms - // we have in the workspace - this.getLikeThisButNotThisQuery = function(startNodes) { - const likeQueries = []; - - const txtsByFieldType = {}; - startNodes.forEach(node => { - let txt = txtsByFieldType[node.data.field]; - if (txt) { - txt = txt + ' ' + node.label; - } else { - txt = node.label; + const backFilledMinLineSize = 2; + const backFilledMaxLineSize = 5; + buckets.forEach(function(bucket) { + if (bucket.doc_count < parseInt(self.options.exploreControls.minDocCount)) { + return; } - txtsByFieldType[node.data.field] = txt; - }); - for (const field in txtsByFieldType) { - if (txtsByFieldType.hasOwnProperty(field)) { - likeQueries.push({ - more_like_this: { - like: txtsByFieldType[field], - min_term_freq: 1, - minimum_should_match: '20%', - min_doc_freq: 1, - boost_terms: 2, - max_query_terms: 25, - }, - }); + const ids = bucket.key.split('|'); + if (ids.length === 2) { + // Bucket represents an edge + const srcNode = nodesForLinking[ids[0]]; + const targetNode = nodesForLinking[ids[1]]; + const edgeId = self.makeEdgeId(srcNode.id, targetNode.id); + const existingEdge = self.edgesMap[edgeId]; + if (existingEdge) { + // Tweak the doc_count score having just looked it up. + existingEdge.doc_count = Math.max(existingEdge.doc_count, bucket.doc_count); + } else { + connections.push({ + // source and target values are indexes into the vertices array + source: parseInt(ids[0]), + target: parseInt(ids[1]), + weight: bucket.weight, + width: Math.max( + backFilledMinLineSize, + (bucket.weight / maxEdgeWeight) * backFilledMaxLineSize + ), + doc_count: bucket.doc_count, + }); + } } + }); + // Trim the array of connections so that we don't add too many at once - disorientating for users otherwise + if (connections.length > maxNewEdges) { + connections = connections.sort(function(a, b) { + return b.weight - a.weight; + }); + connections = connections.slice(0, maxNewEdges); } - const excludeNodesByField = {}; - const allExistingNodes = self.nodes; - allExistingNodes.forEach(existingNode => { - addTermToFieldList(excludeNodesByField, existingNode.data.field, existingNode.data.term); - }); - const blacklistedNodes = self.blacklistedNodes; - blacklistedNodes.forEach(blacklistedNode => { - addTermToFieldList( - excludeNodesByField, - blacklistedNode.data.field, - blacklistedNode.data.term - ); + // Merge the new edges into the existing workspace's graph. + // We reuse the mergeGraph function used to handle the + // results of other calls to the server-side Graph API + // so must package the results here with that same format + // even though we know all the vertices we provide will + // be duplicates and ignored. + self.mergeGraph({ + nodes: vertices, + edges: connections, }); + }); + }; - //Create negative boosting queries to avoid matching what you already have in the workspace. - const notExistingNodes = []; - Object.keys(excludeNodesByField).forEach(fieldName => { - const termsQuery = {}; - termsQuery[fieldName] = excludeNodesByField[fieldName]; - notExistingNodes.push({ - terms: termsQuery, + // Provide a "fuzzy find similar" query that can find similar docs but preferably + // not re-iterating the exact terms we already have in the workspace. + // We use a free-text search on the index's configured default field (typically '_all') + // to drill-down into docs that should be linked but aren't via the exact terms + // we have in the workspace + this.getLikeThisButNotThisQuery = function(startNodes) { + const likeQueries = []; + + const txtsByFieldType = {}; + startNodes.forEach(node => { + let txt = txtsByFieldType[node.data.field]; + if (txt) { + txt = txt + ' ' + node.label; + } else { + txt = node.label; + } + txtsByFieldType[node.data.field] = txt; + }); + for (const field in txtsByFieldType) { + if (txtsByFieldType.hasOwnProperty(field)) { + likeQueries.push({ + more_like_this: { + like: txtsByFieldType[field], + min_term_freq: 1, + minimum_should_match: '20%', + min_doc_freq: 1, + boost_terms: 2, + max_query_terms: 25, + }, }); + } + } + + const excludeNodesByField = {}; + const allExistingNodes = self.nodes; + allExistingNodes.forEach(existingNode => { + addTermToFieldList(excludeNodesByField, existingNode.data.field, existingNode.data.term); + }); + const blacklistedNodes = self.blacklistedNodes; + blacklistedNodes.forEach(blacklistedNode => { + addTermToFieldList( + excludeNodesByField, + blacklistedNode.data.field, + blacklistedNode.data.term + ); + }); + + //Create negative boosting queries to avoid matching what you already have in the workspace. + const notExistingNodes = []; + Object.keys(excludeNodesByField).forEach(fieldName => { + const termsQuery = {}; + termsQuery[fieldName] = excludeNodesByField[fieldName]; + notExistingNodes.push({ + terms: termsQuery, }); + }); - const result = { - // Use a boosting query to effectively to request "similar to these IDS/labels but - // preferably not containing these exact IDs". - boosting: { - negative_boost: 0.0001, - negative: { - bool: { - should: notExistingNodes, - }, + const result = { + // Use a boosting query to effectively to request "similar to these IDS/labels but + // preferably not containing these exact IDs". + boosting: { + negative_boost: 0.0001, + negative: { + bool: { + should: notExistingNodes, }, - positive: { - bool: { - should: likeQueries, - }, + }, + positive: { + bool: { + should: likeQueries, }, }, - }; - return result; + }, }; + return result; + }; - this.getSelectedIntersections = function(callback) { - if (self.selectedNodes.length === 0) { - return self.getAllIntersections(callback, self.nodes); - } - if (self.selectedNodes.length === 1) { - const selectedNode = self.selectedNodes[0]; - const neighbourNodes = self.getNeighbours(selectedNode); - neighbourNodes.push(selectedNode); - return self.getAllIntersections(callback, neighbourNodes); - } - return self.getAllIntersections(callback, self.getAllSelectedNodes()); - }; + this.getSelectedIntersections = function(callback) { + if (self.selectedNodes.length === 0) { + return self.getAllIntersections(callback, self.nodes); + } + if (self.selectedNodes.length === 1) { + const selectedNode = self.selectedNodes[0]; + const neighbourNodes = self.getNeighbours(selectedNode); + neighbourNodes.push(selectedNode); + return self.getAllIntersections(callback, neighbourNodes); + } + return self.getAllIntersections(callback, self.getAllSelectedNodes()); + }; - this.jLHScore = function(subsetFreq, subsetSize, supersetFreq, supersetSize) { - const subsetProbability = subsetFreq / subsetSize; - const supersetProbability = supersetFreq / supersetSize; + this.jLHScore = function(subsetFreq, subsetSize, supersetFreq, supersetSize) { + const subsetProbability = subsetFreq / subsetSize; + const supersetProbability = supersetFreq / supersetSize; - const absoluteProbabilityChange = subsetProbability - supersetProbability; - if (absoluteProbabilityChange <= 0) { - return 0; - } - const relativeProbabilityChange = subsetProbability / supersetProbability; - return absoluteProbabilityChange * relativeProbabilityChange; - }; + const absoluteProbabilityChange = subsetProbability - supersetProbability; + if (absoluteProbabilityChange <= 0) { + return 0; + } + const relativeProbabilityChange = subsetProbability / supersetProbability; + return absoluteProbabilityChange * relativeProbabilityChange; + }; - // Currently unused in the Kibana UI. It was a utility that provided a sorted list - // of recommended node merges for a selection of nodes. Top results would be - // rare nodes that ALWAYS appear alongside more popular ones e.g. text:9200 always - // appears alongside hashtag:elasticsearch so would be offered as a likely candidate - // for merging. - - // Determines union/intersection stats for neighbours of a node. - // TODO - could move server-side as a graph API function? - this.getAllIntersections = function(callback, nodes) { - //Ensure these are all top-level nodes only - nodes = nodes.filter(function(n) { - return n.parent === undefined; - }); + // Currently unused in the Kibana UI. It was a utility that provided a sorted list + // of recommended node merges for a selection of nodes. Top results would be + // rare nodes that ALWAYS appear alongside more popular ones e.g. text:9200 always + // appears alongside hashtag:elasticsearch so would be offered as a likely candidate + // for merging. + + // Determines union/intersection stats for neighbours of a node. + // TODO - could move server-side as a graph API function? + this.getAllIntersections = function(callback, nodes) { + //Ensure these are all top-level nodes only + nodes = nodes.filter(function(n) { + return n.parent === undefined; + }); - const allQueries = nodes.map(function(node) { - return self.buildNodeQuery(node); - }); + const allQueries = nodes.map(function(node) { + return self.buildNodeQuery(node); + }); - const allQuery = { - bool: { - should: allQueries, + const allQuery = { + bool: { + should: allQueries, + }, + }; + //==================== + const request = { + query: allQuery, + size: 0, + aggs: { + all: { + global: {}, }, - }; - //==================== - const request = { - query: allQuery, - size: 0, - aggs: { - all: { - global: {}, + sources: { + // Could use significant_terms not filters to get stats but + // for the fact some of the nodes are groups of terms. + filters: { + filters: {}, }, - sources: { - // Could use significant_terms not filters to get stats but - // for the fact some of the nodes are groups of terms. - filters: { - filters: {}, - }, - aggs: { - targets: { - filters: { - filters: {}, - }, + aggs: { + targets: { + filters: { + filters: {}, }, }, }, }, - }; - allQueries.forEach((query, n) => { - // Add aggs to get intersection stats with root node. - request.aggs.sources.filters.filters['bg' + n] = query; - request.aggs.sources.aggs.targets.filters.filters['fg' + n] = query; + }, + }; + allQueries.forEach((query, n) => { + // Add aggs to get intersection stats with root node. + request.aggs.sources.filters.filters['bg' + n] = query; + request.aggs.sources.aggs.targets.filters.filters['fg' + n] = query; + }); + searcher(self.options.indexName, request, function(data) { + const termIntersects = []; + const fullDocCounts = []; + const allDocCount = data.aggregations.all.doc_count; + + // Gather the background stats for all nodes. + nodes.forEach((rootNode, n) => { + fullDocCounts.push(data.aggregations.sources.buckets['bg' + n].doc_count); }); - searcher(self.options.indexName, request, function(data) { - const termIntersects = []; - const fullDocCounts = []; - const allDocCount = data.aggregations.all.doc_count; - - // Gather the background stats for all nodes. - nodes.forEach((rootNode, n) => { - fullDocCounts.push(data.aggregations.sources.buckets['bg' + n].doc_count); - }); - nodes.forEach((rootNode, n) => { - const t1 = fullDocCounts[n]; - const baseAgg = data.aggregations.sources.buckets['bg' + n].targets.buckets; - nodes.forEach((leafNode, l) => { - const t2 = fullDocCounts[l]; - if (l === n) { - return; - } - if (t1 > t2) { + nodes.forEach((rootNode, n) => { + const t1 = fullDocCounts[n]; + const baseAgg = data.aggregations.sources.buckets['bg' + n].targets.buckets; + nodes.forEach((leafNode, l) => { + const t2 = fullDocCounts[l]; + if (l === n) { + return; + } + if (t1 > t2) { + // We should get the same stats for t2->t1 from the t1->t2 bucket path + return; + } + if (t1 === t2) { + if (rootNode.id > leafNode.id) { // We should get the same stats for t2->t1 from the t1->t2 bucket path return; } - if (t1 === t2) { - if (rootNode.id > leafNode.id) { - // We should get the same stats for t2->t1 from the t1->t2 bucket path - return; - } - } - const t1AndT2 = baseAgg['fg' + l].doc_count; - if (t1AndT2 === 0) { - return; - } - const neighbourNode = nodes[l]; - let t1Label = rootNode.data.label; - if (rootNode.numChildren > 0) { - t1Label += '(+' + rootNode.numChildren + ')'; - } - let t2Label = neighbourNode.data.label; - if (neighbourNode.numChildren > 0) { - t2Label += '(+' + neighbourNode.numChildren + ')'; - } - - // A straight percentage can be poor if t1==1 (100%) - not too much strength of evidence - // var mergeConfidence=t1AndT2/t1; - - // So using Significance heuristic instead - const mergeConfidence = self.jLHScore(t1AndT2, t2, t1, allDocCount); - - const termIntersect = { - id1: rootNode.id, - id2: neighbourNode.id, - term1: t1Label, - term2: t2Label, - v1: t1, - v2: t2, - mergeLeftConfidence: t1AndT2 / t1, - mergeRightConfidence: t1AndT2 / t2, - mergeConfidence: mergeConfidence, - overlap: t1AndT2, - }; - termIntersects.push(termIntersect); - }); - }); - termIntersects.sort(function(a, b) { - if (b.mergeConfidence !== a.mergeConfidence) { - return b.mergeConfidence - a.mergeConfidence; } - // If of equal similarity use the size of the overlap as - // a measure of magnitude/significance for tie-breaker. - - if (b.overlap !== a.overlap) { - return b.overlap - a.overlap; + const t1AndT2 = baseAgg['fg' + l].doc_count; + if (t1AndT2 === 0) { + return; + } + const neighbourNode = nodes[l]; + let t1Label = rootNode.data.label; + if (rootNode.numChildren > 0) { + t1Label += '(+' + rootNode.numChildren + ')'; } - //All other things being equal we now favour where t2 NOT t1 is small. - return a.v2 - b.v2; + let t2Label = neighbourNode.data.label; + if (neighbourNode.numChildren > 0) { + t2Label += '(+' + neighbourNode.numChildren + ')'; + } + + // A straight percentage can be poor if t1==1 (100%) - not too much strength of evidence + // var mergeConfidence=t1AndT2/t1; + + // So using Significance heuristic instead + const mergeConfidence = self.jLHScore(t1AndT2, t2, t1, allDocCount); + + const termIntersect = { + id1: rootNode.id, + id2: neighbourNode.id, + term1: t1Label, + term2: t2Label, + v1: t1, + v2: t2, + mergeLeftConfidence: t1AndT2 / t1, + mergeRightConfidence: t1AndT2 / t2, + mergeConfidence: mergeConfidence, + overlap: t1AndT2, + }; + termIntersects.push(termIntersect); }); - if (callback) { - callback(termIntersects); + }); + termIntersects.sort(function(a, b) { + if (b.mergeConfidence !== a.mergeConfidence) { + return b.mergeConfidence - a.mergeConfidence; + } + // If of equal similarity use the size of the overlap as + // a measure of magnitude/significance for tie-breaker. + + if (b.overlap !== a.overlap) { + return b.overlap - a.overlap; } + //All other things being equal we now favour where t2 NOT t1 is small. + return a.v2 - b.v2; }); - }; + if (callback) { + callback(termIntersects); + } + }); + }; - // Internal utility function for calling the Graph API and handling the response - // by merging results into existing nodes in this workspace. - this.callElasticsearch = function(request) { - self.lastRequest = JSON.stringify(request, null, '\t'); - graphExplorer(self.options.indexName, request, function(data) { - self.lastResponse = JSON.stringify(data, null, '\t'); - const edges = []; - //Label the nodes with field number for CSS styling - data.vertices.forEach(node => { - self.options.vertex_fields.some(fieldDef => { - if (node.field === fieldDef.name) { - node.color = fieldDef.color; - node.icon = fieldDef.icon; - node.fieldDef = fieldDef; - return true; - } - return false; - }); + // Internal utility function for calling the Graph API and handling the response + // by merging results into existing nodes in this workspace. + this.callElasticsearch = function(request) { + self.lastRequest = JSON.stringify(request, null, '\t'); + graphExplorer(self.options.indexName, request, function(data) { + self.lastResponse = JSON.stringify(data, null, '\t'); + const edges = []; + //Label the nodes with field number for CSS styling + data.vertices.forEach(node => { + self.options.vertex_fields.some(fieldDef => { + if (node.field === fieldDef.name) { + node.color = fieldDef.color; + node.icon = fieldDef.icon; + node.fieldDef = fieldDef; + return true; + } + return false; }); + }); - //Size the edges depending on weight - const minLineSize = 2; - const maxLineSize = 10; - let maxEdgeWeight = 0.00000001; - data.connections.forEach(edge => { - maxEdgeWeight = Math.max(maxEdgeWeight, edge.weight); - }); - data.connections.forEach(edge => { - edges.push({ - source: edge.source, - target: edge.target, - doc_count: edge.doc_count, - weight: edge.weight, - width: Math.max(minLineSize, (edge.weight / maxEdgeWeight) * maxLineSize), - }); + //Size the edges depending on weight + const minLineSize = 2; + const maxLineSize = 10; + let maxEdgeWeight = 0.00000001; + data.connections.forEach(edge => { + maxEdgeWeight = Math.max(maxEdgeWeight, edge.weight); + }); + data.connections.forEach(edge => { + edges.push({ + source: edge.source, + target: edge.target, + doc_count: edge.doc_count, + weight: edge.weight, + width: Math.max(minLineSize, (edge.weight / maxEdgeWeight) * maxLineSize), }); - - self.mergeGraph( - { - nodes: data.vertices, - edges: edges, - }, - { - labeller: self.options.labeller, - } - ); }); - }; - } - //===================== - // Begin Kibana wrapper - return { - createWorkspace: createWorkspace, + self.mergeGraph( + { + nodes: data.vertices, + edges: edges, + }, + { + labeller: self.options.labeller, + } + ); + }); }; -})(); +} +//===================== + +// Begin Kibana wrapper +export function createWorkspace(options) { + return new GraphWorkspace(options); +} diff --git a/x-pack/plugins/graph/public/angular/graph_client_workspace.test.js b/x-pack/plugins/graph/public/angular/graph_client_workspace.test.js index 6f81a443086c0..7ffb16d986a21 100644 --- a/x-pack/plugins/graph/public/angular/graph_client_workspace.test.js +++ b/x-pack/plugins/graph/public/angular/graph_client_workspace.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import gws from './graph_client_workspace'; +import { createWorkspace } from './graph_client_workspace'; describe('graphui-workspace', function() { describe('createWorkspace()', function() { @@ -38,7 +38,7 @@ describe('graphui-workspace', function() { minDocCount: 1, }, }; - const workspace = gws.createWorkspace(options); + const workspace = createWorkspace(options); return { workspace, //, get to(){} diff --git a/x-pack/plugins/graph/public/app.js b/x-pack/plugins/graph/public/app.js index 53175d18e629f..7effe44375b1f 100644 --- a/x-pack/plugins/graph/public/app.js +++ b/x-pack/plugins/graph/public/app.js @@ -23,7 +23,7 @@ import { Listing } from './components/listing'; import { Settings } from './components/settings'; import { GraphVisualization } from './components/graph_visualization'; -import gws from './angular/graph_client_workspace.js'; +import { createWorkspace } from './angular/graph_client_workspace.js'; import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url'; import { createCachedIndexPatternProvider } from './services/index_pattern_cache'; import { urlTemplateRegex } from './helpers/url_template'; @@ -277,7 +277,7 @@ export function initGraphApp(angularModule, deps) { searchProxy: callSearchNodeProxy, exploreControls, }; - $scope.workspace = gws.createWorkspace(options); + $scope.workspace = createWorkspace(options); }, setLiveResponseFields: fields => { $scope.liveResponseFields = fields; diff --git a/x-pack/plugins/ml/public/application/settings/calendars/edit/import_modal/utils.js b/x-pack/plugins/ml/public/application/settings/calendars/edit/import_modal/utils.js index b8a14650d3fd5..d24577826838e 100644 --- a/x-pack/plugins/ml/public/application/settings/calendars/edit/import_modal/utils.js +++ b/x-pack/plugins/ml/public/application/settings/calendars/edit/import_modal/utils.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -const icalendar = require('icalendar'); +import icalendar from 'icalendar'; import moment from 'moment'; import { generateTempId } from '../utils'; diff --git a/x-pack/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js b/x-pack/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js index 02165b659407f..31dbddfcd17ea 100644 --- a/x-pack/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js +++ b/x-pack/plugins/monitoring/public/components/sparkline/__mocks__/plugins/xpack_main/jquery_flot.js @@ -6,15 +6,12 @@ /* eslint-env jest */ -function $() { +export function $() { return { on: jest.fn(), off: jest.fn(), + plot: () => ({ + shutdown: jest.fn(), + }), }; } - -$.plot = () => ({ - shutdown: jest.fn(), -}); - -module.exports = $; From 4330865a6ca67e9e9802b3833307e680091c0621 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 5 May 2020 18:33:22 +0200 Subject: [PATCH 10/72] Hide chrome until an app is mounting or mounted to avoid FOC on chromeless apps (#65036) * hidden chrome until an application is mounted * emits currentAppId$ before executing mount handler * address comments --- .../application/application_service.tsx | 41 ++++++------ .../application_service.test.tsx | 64 +++++++++++++++++++ src/core/public/chrome/chrome_service.test.ts | 28 ++++---- src/core/public/chrome/chrome_service.tsx | 23 +++---- src/core/public/core_system.ts | 1 - 5 files changed, 109 insertions(+), 48 deletions(-) diff --git a/src/core/public/application/application_service.tsx b/src/core/public/application/application_service.tsx index 0dd77072e9eaf..8442f1ecc6411 100644 --- a/src/core/public/application/application_service.tsx +++ b/src/core/public/application/application_service.tsx @@ -26,6 +26,7 @@ import { InjectedMetadataSetup } from '../injected_metadata'; import { HttpSetup, HttpStart } from '../http'; import { OverlayStart } from '../overlays'; import { ContextSetup, IContextContainer } from '../context'; +import { PluginOpaqueId } from '../plugins'; import { AppRouter } from './ui'; import { Capabilities, CapabilitiesService } from './capabilities'; import { @@ -34,7 +35,6 @@ import { AppLeaveHandler, AppMount, AppMountDeprecated, - AppMounter, AppNavLinkStatus, AppStatus, AppUpdatableFields, @@ -145,6 +145,25 @@ export class ApplicationService { this.subscriptions.push(subscription); }; + const wrapMount = (plugin: PluginOpaqueId, app: App): AppMount => { + let handler: AppMount; + if (isAppMountDeprecated(app.mount)) { + handler = this.mountContext!.createHandler(plugin, app.mount); + if (process.env.NODE_ENV === 'development') { + // eslint-disable-next-line no-console + console.warn( + `App [${app.id}] is using deprecated mount context. Use core.getStartServices() instead.` + ); + } + } else { + handler = app.mount; + } + return async params => { + this.currentAppId$.next(app.id); + return handler(params); + }; + }; + return { registerMountContext: this.mountContext!.registerContext, register: (plugin, app: App) => { @@ -162,24 +181,6 @@ export class ApplicationService { throw new Error('Cannot register an application route that includes HTTP base path'); } - let handler: AppMount; - - if (isAppMountDeprecated(app.mount)) { - handler = this.mountContext!.createHandler(plugin, app.mount); - // eslint-disable-next-line no-console - console.warn( - `App [${app.id}] is using deprecated mount context. Use core.getStartServices() instead.` - ); - } else { - handler = app.mount; - } - - const mount: AppMounter = async params => { - const unmount = await handler(params); - this.currentAppId$.next(app.id); - return unmount; - }; - const { updater$, ...appProps } = app; this.apps.set(app.id, { ...appProps, @@ -193,7 +194,7 @@ export class ApplicationService { this.mounters.set(app.id, { appRoute: app.appRoute!, appBasePath: basePath.prepend(app.appRoute!), - mount, + mount: wrapMount(plugin, app), unmountBeforeMounting: false, }); }, diff --git a/src/core/public/application/integration_tests/application_service.test.tsx b/src/core/public/application/integration_tests/application_service.test.tsx index edf3583f384b8..60c36d3e330e0 100644 --- a/src/core/public/application/integration_tests/application_service.test.tsx +++ b/src/core/public/application/integration_tests/application_service.test.tsx @@ -17,6 +17,7 @@ * under the License. */ +import { take } from 'rxjs/operators'; import { createRenderer } from './utils'; import { createMemoryHistory, MemoryHistory } from 'history'; import { ApplicationService } from '../application_service'; @@ -56,6 +57,69 @@ describe('ApplicationService', () => { service = new ApplicationService(); }); + describe('navigating to apps', () => { + describe('using history.push', () => { + it('emits currentAppId$ before mounting the app', async () => { + const { register } = service.setup(setupDeps); + + let resolveMount: () => void; + const promise = new Promise(resolve => { + resolveMount = resolve; + }); + + register(Symbol(), { + id: 'app1', + title: 'App1', + mount: async ({}: AppMountParameters) => { + await promise; + return () => undefined; + }, + }); + + const { currentAppId$, getComponent } = await service.start(startDeps); + update = createRenderer(getComponent()); + + await navigate('/app/app1'); + + expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1'); + + resolveMount!(); + + expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1'); + }); + }); + + describe('using navigateToApp', () => { + it('emits currentAppId$ before mounting the app', async () => { + const { register } = service.setup(setupDeps); + + let resolveMount: () => void; + const promise = new Promise(resolve => { + resolveMount = resolve; + }); + + register(Symbol(), { + id: 'app1', + title: 'App1', + mount: async ({}: AppMountParameters) => { + await promise; + return () => undefined; + }, + }); + + const { navigateToApp, currentAppId$ } = await service.start(startDeps); + + await navigateToApp('app1'); + + expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1'); + + resolveMount!(); + + expect(await currentAppId$.pipe(take(1)).toPromise()).toEqual('app1'); + }); + }); + }); + describe('leaving an application that registered an app leave handler', () => { it('navigates to the new app if action is default', async () => { startDeps.overlays.openConfirm.mockResolvedValue(true); diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index bf531aaa00fac..a765ed47ea712 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -29,7 +29,6 @@ import { notificationServiceMock } from '../notifications/notifications_service. import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { ChromeService } from './chrome_service'; import { App } from '../application'; -import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; class FakeApp implements App { public title = `${this.id} App`; @@ -52,7 +51,6 @@ function defaultStartDeps(availableApps?: App[]) { http: httpServiceMock.createStartContract(), injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), - uiSettings: uiSettingsServiceMock.createStartContract(), }; if (availableApps) { @@ -163,7 +161,7 @@ describe('start', () => { }); describe('visibility', () => { - it('updates/emits the visibility', async () => { + it('emits false when no application is mounted', async () => { const { chrome, service } = await start(); const promise = chrome .getIsVisible$() @@ -177,33 +175,37 @@ describe('start', () => { await expect(promise).resolves.toMatchInlineSnapshot(` Array [ - true, - true, false, - true, + false, + false, + false, ] `); }); - it('always emits false if embed query string is preset when set up', async () => { + it('emits false until manually overridden when in embed mode', async () => { window.history.pushState(undefined, '', '#/home?a=b&embed=true'); + const startDeps = defaultStartDeps([new FakeApp('alpha')]); + const { navigateToApp } = startDeps.application; + const { chrome, service } = await start({ startDeps }); - const { chrome, service } = await start(); const promise = chrome .getIsVisible$() .pipe(toArray()) .toPromise(); + await navigateToApp('alpha'); + chrome.setIsVisible(true); chrome.setIsVisible(false); - chrome.setIsVisible(true); + service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` Array [ false, false, - false, + true, false, ] `); @@ -228,7 +230,7 @@ describe('start', () => { await expect(promise).resolves.toMatchInlineSnapshot(` Array [ - true, + false, true, false, true, @@ -245,13 +247,13 @@ describe('start', () => { .pipe(toArray()) .toPromise(); - navigateToApp('alpha'); + await navigateToApp('alpha'); chrome.setIsVisible(true); service.stop(); await expect(promise).resolves.toMatchInlineSnapshot(` Array [ - true, + false, false, false, ] diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 7c9b644b8b984..3d9eeff09ecce 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -38,7 +38,6 @@ import { LoadingIndicator, Header } from './ui'; import { DocLinksStart } from '../doc_links'; import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; import { KIBANA_ASK_ELASTIC_LINK } from './constants'; -import { IUiSettingsClient } from '../ui_settings'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; const IS_LOCKED_KEY = 'core.chrome.isLocked'; @@ -85,14 +84,12 @@ interface StartDeps { http: HttpStart; injectedMetadata: InjectedMetadataStart; notifications: NotificationsStart; - uiSettings: IUiSettingsClient; } /** @internal */ export class ChromeService { private isVisible$!: Observable; - private appHidden$!: Observable; - private toggleHidden$!: BehaviorSubject; + private isForceHidden$!: BehaviorSubject; private readonly stop$ = new ReplaySubject(1); private readonly navControls = new NavControlsService(); private readonly navLinks = new NavLinksService(); @@ -111,13 +108,12 @@ export class ChromeService { private initVisibility(application: StartDeps['application']) { // Start off the chrome service hidden if "embed" is in the hash query string. const isEmbedded = 'embed' in parse(location.hash.slice(1), true).query; + this.isForceHidden$ = new BehaviorSubject(isEmbedded); - this.toggleHidden$ = new BehaviorSubject(isEmbedded); - this.appHidden$ = merge( - // Default the app being hidden to the same value initial value as the chrome visibility - // in case the application service has not emitted an app ID yet, since we want to trigger - // combineLatest below regardless of having an application value yet. - of(isEmbedded), + const appHidden$ = merge( + // For the isVisible$ logic, having no mounted app is equivalent to having a hidden app + // in the sense that the chrome UI should not be displayed until a non-chromeless app is mounting or mounted + of(true), application.currentAppId$.pipe( flatMap(appId => application.applications$.pipe( @@ -128,8 +124,8 @@ export class ChromeService { ) ) ); - this.isVisible$ = combineLatest([this.appHidden$, this.toggleHidden$]).pipe( - map(([appHidden, toggleHidden]) => !(appHidden || toggleHidden)), + this.isVisible$ = combineLatest([appHidden$, this.isForceHidden$]).pipe( + map(([appHidden, forceHidden]) => !appHidden && !forceHidden), takeUntil(this.stop$) ); } @@ -140,7 +136,6 @@ export class ChromeService { http, injectedMetadata, notifications, - uiSettings, }: StartDeps): Promise { this.initVisibility(application); @@ -221,7 +216,7 @@ export class ChromeService { getIsVisible$: () => this.isVisible$, - setIsVisible: (isVisible: boolean) => this.toggleHidden$.next(!isVisible), + setIsVisible: (isVisible: boolean) => this.isForceHidden$.next(!isVisible), getApplicationClasses$: () => applicationClasses$.pipe( diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index e58114b69dcc1..59f0142bb8890 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -240,7 +240,6 @@ export class CoreSystem { http, injectedMetadata, notifications, - uiSettings, }); application.registerMountContext(this.coreContext.coreId, 'core', () => ({ From 0b202dc5dd236d6cc581a1c75b90e311ea4175a0 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 5 May 2020 09:40:34 -0700 Subject: [PATCH 11/72] [Metrics UI] Add 99th and 95th percentiles to Metric Explorer (#64699) * [Metrics UI] Add 99th and 95th percentiles to Metric Exploer Aggregations * Removing unused dependency; fixing types --- .../infra/common/http_api/metrics_explorer.ts | 2 ++ .../infra/common/inventory_models/types.ts | 15 +++++++++ .../components/aggregation.tsx | 6 ++++ .../components/helpers/calculate_domain.ts | 3 +- .../components/helpers/get_metric_id.ts | 14 ++++++++ .../lib/create_metrics_model.ts | 32 +++++++++++++++++-- 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/get_metric_id.ts diff --git a/x-pack/plugins/infra/common/http_api/metrics_explorer.ts b/x-pack/plugins/infra/common/http_api/metrics_explorer.ts index eb5b0bdbcfbc5..07d5fe59a9718 100644 --- a/x-pack/plugins/infra/common/http_api/metrics_explorer.ts +++ b/x-pack/plugins/infra/common/http_api/metrics_explorer.ts @@ -14,6 +14,8 @@ export const METRIC_EXPLORER_AGGREGATIONS = [ 'rate', 'count', 'sum', + 'p95', + 'p99', ] as const; type MetricExplorerAggregations = typeof METRIC_EXPLORER_AGGREGATIONS[number]; diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/infra/common/inventory_models/types.ts index a6773d0a07450..35d83440812d5 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/infra/common/inventory_models/types.ts @@ -152,11 +152,26 @@ export const TSVBMetricModelSeriesAggRT = rt.type({ type: rt.literal('series_agg'), }); +export const TSVBPercentileItemRT = rt.type({ + id: rt.string, + value: rt.number, +}); + +export const TSVBMetricModePercentileAggRT = rt.intersection([ + rt.type({ + id: rt.string, + type: rt.literal('percentile'), + percentiles: rt.array(TSVBPercentileItemRT), + }), + rt.partial({ field: rt.string }), +]); + export const TSVBMetricRT = rt.union([ TSVBMetricModelCountRT, TSVBMetricModelBasicMetricRT, TSVBMetricModelBucketScriptRT, TSVBMetricModelDerivativeRT, + TSVBMetricModePercentileAggRT, TSVBMetricModelSeriesAggRT, ]); export type TSVBMetric = rt.TypeOf; diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx index 5a84d204b3b25..8d397d9f96b59 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/aggregation.tsx @@ -41,6 +41,12 @@ export const MetricsExplorerAggregationPicker = ({ options, onChange }: Props) = ['rate']: i18n.translate('xpack.infra.metricsExplorer.aggregationLables.rate', { defaultMessage: 'Rate', }), + ['p95']: i18n.translate('xpack.infra.metricsExplorer.aggregationLables.p95', { + defaultMessage: '95th Percentile', + }), + ['p99']: i18n.translate('xpack.infra.metricsExplorer.aggregationLables.p99', { + defaultMessage: '99th Percentile', + }), ['count']: i18n.translate('xpack.infra.metricsExplorer.aggregationLables.count', { defaultMessage: 'Document count', }), diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/calculate_domain.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/calculate_domain.ts index 811486d355f2e..5cfc8c366b444 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/calculate_domain.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/calculate_domain.ts @@ -6,6 +6,7 @@ import { min, max, sum, isNumber } from 'lodash'; import { MetricsExplorerSeries } from '../../../../../../common/http_api/metrics_explorer'; import { MetricsExplorerOptionsMetric } from '../../hooks/use_metrics_explorer_options'; +import { getMetricId } from './get_metric_id'; const getMin = (values: Array) => { const minValue = min(values); @@ -26,7 +27,7 @@ export const calculateDomain = ( .reduce((acc, row) => { const rowValues = metrics .map((m, index) => { - return (row[`metric_${index}`] as number) || null; + return (row[getMetricId(m, index)] as number) || null; }) .filter(v => isNumber(v)); const minValue = getMin(rowValues); diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/get_metric_id.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/get_metric_id.ts new file mode 100644 index 0000000000000..35ca2561b0862 --- /dev/null +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/get_metric_id.ts @@ -0,0 +1,14 @@ +/* + * 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 { MetricsExplorerOptionsMetric } from '../../hooks/use_metrics_explorer_options'; + +export const getMetricId = (metric: MetricsExplorerOptionsMetric, index: string | number) => { + if (['p95', 'p99'].includes(metric.aggregation)) { + return `metric_${index}:percentile_0`; + } + return `metric_${index}`; +}; diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/create_metrics_model.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/create_metrics_model.ts index c537ba0d5163e..a7f393261a096 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/create_metrics_model.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/create_metrics_model.ts @@ -4,9 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { InfraMetricModelMetricType } from '../../../lib/adapters/metrics'; import { MetricsExplorerRequestBody } from '../../../../common/http_api/metrics_explorer'; import { TSVBMetricModel } from '../../../../common/inventory_models/types'; + +const percentileToVaue = (agg: 'p95' | 'p99') => { + if (agg === 'p95') { + return 95; + } + return 99; +}; + export const createMetricModel = (options: MetricsExplorerRequestBody): TSVBMetricModel => { return { id: 'custom', @@ -47,6 +54,27 @@ export const createMetricModel = (options: MetricsExplorerRequestBody): TSVBMetr ], }; } + + if (metric.aggregation === 'p95' || metric.aggregation === 'p99') { + return { + id: `metric_${index}`, + split_mode: 'everything', + metrics: [ + { + field: metric.field, + id: `metric_${metric.aggregation}_${index}`, + type: 'percentile', + percentiles: [ + { + id: 'percentile_0', + value: percentileToVaue(metric.aggregation), + }, + ], + }, + ], + }; + } + // Create a basic TSVB series with a single metric const aggregation = metric.aggregation || 'avg'; @@ -57,7 +85,7 @@ export const createMetricModel = (options: MetricsExplorerRequestBody): TSVBMetr { field: metric.field, id: `metric_${aggregation}_${index}`, - type: InfraMetricModelMetricType[aggregation], + type: aggregation, }, ], }; From db914a8986c88e1c10ed3a2811e281e96354fa30 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 5 May 2020 19:02:58 +0200 Subject: [PATCH 12/72] [Uptime] Move status filter to monitor list (#65049) --- .../common/runtime_types/ping/histogram.ts | 1 - .../ping_histogram_container.tsx | 5 +- .../overview/filter_group/filter_group.tsx | 18 --- .../filter_status_button.test.tsx.snap | 25 ++++ .../__snapshots__/monitor_list.test.tsx.snap | 111 ++++++++++++--- .../__snapshots__/status_filter.test.tsx.snap | 128 ++++++++++++++++++ .../__tests__/filter_status_button.test.tsx | 10 +- .../__tests__/status_filter.test.tsx | 64 +++++++++ .../filter_status_button.tsx | 11 +- .../overview/monitor_list/monitor_list.tsx | 31 +---- .../monitor_list/monitor_list_header.tsx | 49 +++++++ .../overview/monitor_list/status_filter.tsx | 55 ++++++++ .../overview/snapshot/snapshot_container.tsx | 8 +- .../uptime/public/state/actions/snapshot.ts | 1 - .../state/api/__tests__/snapshot.test.ts | 3 - .../plugins/uptime/public/state/api/ping.ts | 2 - .../state/reducers/__tests__/snapshot.test.ts | 1 - .../get_ping_histogram.test.ts.snap | 46 +------ .../__tests__/get_ping_histogram.test.ts | 41 ------ .../server/lib/requests/get_ping_histogram.ts | 8 +- .../lib/requests/get_snapshot_counts.ts | 17 +-- .../rest_api/pings/get_ping_histogram.ts | 4 +- .../rest_api/snapshot/get_snapshot_count.ts | 4 +- .../fixtures/snapshot_filtered_by_down.json | 5 - .../fixtures/snapshot_filtered_by_up.json | 5 - .../apis/uptime/rest/snapshot.ts | 17 --- .../test/functional/apps/uptime/overview.ts | 13 +- 27 files changed, 458 insertions(+), 225 deletions(-) rename x-pack/plugins/uptime/public/components/overview/{filter_group => monitor_list}/__tests__/__snapshots__/filter_status_button.test.tsx.snap (71%) create mode 100644 x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/status_filter.test.tsx.snap rename x-pack/plugins/uptime/public/components/overview/{filter_group => monitor_list}/__tests__/filter_status_button.test.tsx (73%) create mode 100644 x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/status_filter.test.tsx rename x-pack/plugins/uptime/public/components/overview/{filter_group => monitor_list}/filter_status_button.tsx (83%) create mode 100644 x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_header.tsx create mode 100644 x-pack/plugins/uptime/public/components/overview/monitor_list/status_filter.tsx delete mode 100644 x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json delete mode 100644 x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json diff --git a/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts b/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts index 2c3b52051be0f..209770a19f4aa 100644 --- a/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts +++ b/x-pack/plugins/uptime/common/runtime_types/ping/histogram.ts @@ -21,7 +21,6 @@ export interface GetPingHistogramParams { dateEnd: string; filters?: string; monitorId?: string; - statusFilter?: string; } export interface HistogramResult { diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx b/x-pack/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx index c0e17966f5b9f..ad855419d8865 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx @@ -19,7 +19,6 @@ interface Props { const Container: React.FC = ({ height }) => { const { - statusFilter, absoluteDateRangeStart, absoluteDateRangeEnd, dateRangeStart: dateStart, @@ -32,8 +31,8 @@ const Container: React.FC = ({ height }) => { const { loading, data, esKuery, lastRefresh } = useSelector(selectPingHistogram); useEffect(() => { - dispatch(getPingHistogram({ monitorId, dateStart, dateEnd, statusFilter, filters: esKuery })); - }, [dateStart, dateEnd, monitorId, statusFilter, lastRefresh, esKuery, dispatch]); + dispatch(getPingHistogram({ monitorId, dateStart, dateEnd, filters: esKuery })); + }, [dateStart, dateEnd, monitorId, lastRefresh, esKuery, dispatch]); return ( = ({ return ( - - {filterPopoverProps.map(item => ( ))} diff --git a/x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap similarity index 71% rename from x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap rename to x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap index 2d21c4d2fe2a2..b5d1b1d8ff60e 100644 --- a/x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/filter_status_button.test.tsx.snap @@ -1,6 +1,30 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`FilterStatusButton renders without errors for valid props 1`] = ` + +`; + +exports[`FilterStatusButton shallow renders without errors for valid props 1`] = ` diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap index 0d6638e7070d6..7772b886f7a4f 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap @@ -533,22 +533,26 @@ exports[`MonitorList component renders loading state 1`] = ` `; exports[`MonitorList component renders the monitor list 1`] = ` -.c1 { +.c2 { padding-left: 17px; } -.c3 { +.c4 { padding-top: 12px; } -.c2 { +.c0 { + margin-left: auto; +} + +.c3 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } @media (max-width:574px) { - .c0 { + .c1 { min-width: 230px; } } @@ -557,28 +561,101 @@ exports[`MonitorList component renders the monitor list 1`] = ` class="euiPanel euiPanel--paddingMedium" >
- Monitor status + Monitors
+
+ + + +
+
+ @@ -726,7 +803,7 @@ exports[`MonitorList component renders the monitor list 1`] = ` class="euiTableCellContent euiTableCellContent--overflowingContent" >
+ + +
+`; + +exports[`StatusFilterComponent shallow renders without errors for valid props 1`] = ` + + + +`; diff --git a/x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/filter_status_button.test.tsx similarity index 73% rename from x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx rename to x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/filter_status_button.test.tsx index 2ad4d971cf3b0..58c305f0d15a0 100644 --- a/x-pack/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/filter_status_button.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { FilterStatusButton, FilterStatusButtonProps } from '../filter_status_button'; -import { shallowWithRouter } from '../../../../lib'; +import { renderWithRouter, shallowWithRouter } from '../../../../lib'; describe('FilterStatusButton', () => { let props: FilterStatusButtonProps; @@ -16,11 +16,17 @@ describe('FilterStatusButton', () => { dataTestSubj: 'foo', value: 'up', withNext: true, + isActive: true, }; }); - it('renders without errors for valid props', () => { + it('shallow renders without errors for valid props', () => { const wrapper = shallowWithRouter(); expect(wrapper).toMatchSnapshot(); }); + + it('renders without errors for valid props', () => { + const wrapper = renderWithRouter(); + expect(wrapper).toMatchSnapshot(); + }); }); diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/status_filter.test.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/status_filter.test.tsx new file mode 100644 index 0000000000000..a1288513eb785 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/__tests__/status_filter.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { mountWithRouter, renderWithRouter, shallowWithRouter } from '../../../../lib'; +import { createMemoryHistory } from 'history'; +import { StatusFilter } from '../status_filter'; +import { FilterStatusButton } from '../filter_status_button'; + +describe('StatusFilterComponent', () => { + beforeEach(() => {}); + + const getStatusBtns = (status: string) => { + const history = createMemoryHistory({ + initialEntries: [`/?g=%22%22&statusFilter=${status}`], + }); + + const wrapper = mountWithRouter(, history); + const filterBtns = wrapper.find(FilterStatusButton); + + const allBtn = filterBtns.at(0); + const upBtn = filterBtns.at(1); + const downBtn = filterBtns.at(2); + + return { allBtn, upBtn, downBtn, wrapper }; + }; + + it('shallow renders without errors for valid props', () => { + const wrapper = shallowWithRouter(); + expect(wrapper).toMatchSnapshot(); + }); + + it('renders without errors for valid props', () => { + const wrapper = renderWithRouter(); + expect(wrapper).toMatchSnapshot(); + }); + + it('checks if it properly validates url state when filter is up', () => { + const { allBtn, upBtn, downBtn } = getStatusBtns('up'); + + expect(allBtn.props().isActive).toBe(false); + expect(upBtn.props().isActive).toBe(true); + expect(downBtn.props().isActive).toBe(false); + }); + + it('checks if it properly validates url state when filter is down', () => { + const { allBtn, upBtn, downBtn } = getStatusBtns('down'); + + expect(allBtn.props().isActive).toBe(false); + expect(upBtn.props().isActive).toBe(false); + expect(downBtn.props().isActive).toBe(true); + }); + + it('checks if it properly validates url state when filter is all', () => { + const { allBtn, upBtn, downBtn } = getStatusBtns(''); + + expect(allBtn.props().isActive).toBe(true); + expect(upBtn.props().isActive).toBe(false); + expect(downBtn.props().isActive).toBe(false); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_status_button.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/filter_status_button.tsx similarity index 83% rename from x-pack/plugins/uptime/public/components/overview/filter_group/filter_status_button.tsx rename to x-pack/plugins/uptime/public/components/overview/monitor_list/filter_status_button.tsx index abbe72530fd80..6e63c21d08ca9 100644 --- a/x-pack/plugins/uptime/public/components/overview/filter_group/filter_status_button.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/filter_status_button.tsx @@ -9,26 +9,31 @@ import React from 'react'; import { useUrlParams } from '../../../hooks'; export interface FilterStatusButtonProps { - content: string; + content: string | JSX.Element; dataTestSubj: string; isDisabled?: boolean; - value: string; + isActive: boolean; + value: 'up' | 'down' | ''; withNext: boolean; + color?: string; } export const FilterStatusButton = ({ content, dataTestSubj, isDisabled, + isActive, value, + color, withNext, }: FilterStatusButtonProps) => { const [getUrlParams, setUrlParams] = useUrlParams(); const { statusFilter: urlValue } = getUrlParams(); return ( { const nextFilter = { statusFilter: urlValue === value ? '' : value, pagination: '' }; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx index 616d8fbd76043..de53c52cd7f75 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx @@ -13,12 +13,9 @@ import { EuiLink, EuiPanel, EuiSpacer, - EuiTitle, } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; -import { Link } from 'react-router-dom'; import { HistogramPoint, FetchMonitorStatesQueryArgs } from '../../../../common/runtime_types'; import { MonitorSummary } from '../../../../common/runtime_types'; import { MonitorListStatusColumn } from './monitor_list_status_column'; @@ -32,8 +29,8 @@ import { MonitorListDrawer } from './monitor_list_drawer/list_drawer_container'; import { MonitorListProps } from './monitor_list_container'; import { MonitorList } from '../../../state/reducers/monitor_list'; import { useUrlParams } from '../../../hooks'; -import { CERTIFICATES_ROUTE } from '../../../../common/constants'; import { CertStatusColumn } from './cert_status_column'; +import { MonitorListHeader } from './monitor_list_header'; interface Props extends MonitorListProps { lastRefresh: number; @@ -190,31 +187,7 @@ export const MonitorListComponent: React.FC = ({ return ( - - - -
- -
-
-
- - -
- - - -
-
-
-
- + { + return ( + + + +
+ +
+
+
+ + + + + +
+ + + +
+
+
+
+ ); +}; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/status_filter.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/status_filter.tsx new file mode 100644 index 0000000000000..43a7ffcea0867 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/status_filter.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiFilterGroup, EuiTextColor } from '@elastic/eui'; +import { FilterStatusButton } from './filter_status_button'; +import { useGetUrlParams } from '../../../hooks'; + +export const StatusFilter: React.FC = () => { + const { statusFilter } = useGetUrlParams(); + + // Empty string for all filter button value, since we dont store it in url, so keeping it in sync + const ALL = ''; + + return ( + + + + {i18n.translate('xpack.uptime.filterBar.filterUpLabel', { + defaultMessage: 'Up', + })} + + } + dataTestSubj="xpack.uptime.filterBar.filterStatusUp" + value="up" + withNext={true} + isActive={statusFilter === 'up'} + /> + + + ); +}; diff --git a/x-pack/plugins/uptime/public/components/overview/snapshot/snapshot_container.tsx b/x-pack/plugins/uptime/public/components/overview/snapshot/snapshot_container.tsx index 09d30e049175c..0fd52f0a0be4f 100644 --- a/x-pack/plugins/uptime/public/components/overview/snapshot/snapshot_container.tsx +++ b/x-pack/plugins/uptime/public/components/overview/snapshot/snapshot_container.tsx @@ -19,16 +19,14 @@ interface Props { } export const Snapshot: React.FC = ({ height }: Props) => { - const { dateRangeStart, dateRangeEnd, statusFilter } = useGetUrlParams(); + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); const { count, lastRefresh, loading, esKuery } = useSelector(snapshotDataSelector); const dispatch = useDispatch(); useEffect(() => { - dispatch( - getSnapshotCountAction({ dateRangeStart, dateRangeEnd, filters: esKuery, statusFilter }) - ); - }, [dateRangeStart, dateRangeEnd, esKuery, lastRefresh, statusFilter, dispatch]); + dispatch(getSnapshotCountAction({ dateRangeStart, dateRangeEnd, filters: esKuery })); + }, [dateRangeStart, dateRangeEnd, esKuery, lastRefresh, dispatch]); return ; }; diff --git a/x-pack/plugins/uptime/public/state/actions/snapshot.ts b/x-pack/plugins/uptime/public/state/actions/snapshot.ts index e819a553e61f5..cbb7095eabb6c 100644 --- a/x-pack/plugins/uptime/public/state/actions/snapshot.ts +++ b/x-pack/plugins/uptime/public/state/actions/snapshot.ts @@ -11,7 +11,6 @@ export interface GetSnapshotPayload { dateRangeStart: string; dateRangeEnd: string; filters?: string; - statusFilter?: string; } export const getSnapshotCountAction = createAction('GET_SNAPSHOT_COUNT'); diff --git a/x-pack/plugins/uptime/public/state/api/__tests__/snapshot.test.ts b/x-pack/plugins/uptime/public/state/api/__tests__/snapshot.test.ts index ff9fcd0573257..89f3373dacdd3 100644 --- a/x-pack/plugins/uptime/public/state/api/__tests__/snapshot.test.ts +++ b/x-pack/plugins/uptime/public/state/api/__tests__/snapshot.test.ts @@ -30,14 +30,12 @@ describe('snapshot API', () => { dateRangeStart: 'now-15m', dateRangeEnd: 'now', filters: 'monitor.id:"auto-http-0X21EE76EAC459873F"', - statusFilter: 'up', }); expect(fetchMock).toHaveBeenCalledWith('/api/uptime/snapshot/count', { query: { dateRangeEnd: 'now', dateRangeStart: 'now-15m', filters: 'monitor.id:"auto-http-0X21EE76EAC459873F"', - statusFilter: 'up', }, }); expect(resp).toEqual({ up: 3, down: 12, total: 15 }); @@ -50,7 +48,6 @@ describe('snapshot API', () => { dateRangeStart: 'now-15m', dateRangeEnd: 'now', filters: 'monitor.id: baz', - statusFilter: 'up', }); expect(result).toMatchSnapshot(); diff --git a/x-pack/plugins/uptime/public/state/api/ping.ts b/x-pack/plugins/uptime/public/state/api/ping.ts index 6de27879a49f5..a2937c9c794dd 100644 --- a/x-pack/plugins/uptime/public/state/api/ping.ts +++ b/x-pack/plugins/uptime/public/state/api/ping.ts @@ -24,14 +24,12 @@ export const fetchPingHistogram: APIFn monitorId, dateStart, dateEnd, - statusFilter, filters, }) => { const queryParams = { dateStart, dateEnd, monitorId, - statusFilter, filters, }; diff --git a/x-pack/plugins/uptime/public/state/reducers/__tests__/snapshot.test.ts b/x-pack/plugins/uptime/public/state/reducers/__tests__/snapshot.test.ts index 3650422571ce8..40e365f0a13a7 100644 --- a/x-pack/plugins/uptime/public/state/reducers/__tests__/snapshot.test.ts +++ b/x-pack/plugins/uptime/public/state/reducers/__tests__/snapshot.test.ts @@ -17,7 +17,6 @@ describe('snapshot reducer', () => { dateRangeStart: 'now-15m', dateRangeEnd: 'now', filters: 'foo: bar', - statusFilter: 'up', }); expect( snapshotReducer( diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap index 0dafa5144c25a..37dec410664ef 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/__snapshots__/get_ping_histogram.test.ts.snap @@ -31,19 +31,19 @@ Object { "histogram": Array [ Object { "downCount": 1, - "upCount": 0, + "upCount": 2, "x": 1, "y": 1, }, Object { "downCount": 2, - "upCount": 0, + "upCount": 2, "x": 2, "y": 1, }, Object { "downCount": 1, - "upCount": 0, + "upCount": 3, "x": 3, "y": 1, }, @@ -52,46 +52,6 @@ Object { } `; -exports[`getPingHistogram returns a down-filtered array for when filtered by down status 1`] = ` -Object { - "histogram": Array [ - Object { - "downCount": 1, - "upCount": 0, - "x": 1, - "y": 1, - }, - Object { - "downCount": undefined, - "upCount": 0, - "x": 2, - "y": 1, - }, - ], - "interval": "1d", -} -`; - -exports[`getPingHistogram returns a down-filtered array for when filtered by up status 1`] = ` -Object { - "histogram": Array [ - Object { - "downCount": 0, - "upCount": 2, - "x": 1, - "y": 1, - }, - Object { - "downCount": 0, - "upCount": 2, - "x": 2, - "y": 1, - }, - ], - "interval": "1s", -} -`; - exports[`getPingHistogram returns a single bucket if array has 1 1`] = ` Object { "histogram": Array [ diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts index e456670a5e68d..9042186145eb7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_ping_histogram.test.ts @@ -145,7 +145,6 @@ describe('getPingHistogram', () => { to: '5678', filters: JSON.stringify(searchFilter), monitorId: undefined, - statusFilter: 'down', }); expect(mockEsClient).toHaveBeenCalledTimes(1); @@ -205,44 +204,4 @@ describe('getPingHistogram', () => { expect(mockEsClient).toHaveBeenCalledTimes(1); expect(result).toMatchSnapshot(); }); - - it('returns a down-filtered array for when filtered by down status', async () => { - expect.assertions(2); - const mockEsClient = jest.fn(); - standardMockResponse.aggregations.timeseries.interval = '1d'; - mockEsClient.mockReturnValue(standardMockResponse); - const result = await getPingHistogram({ - callES: mockEsClient, - dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, - from: '1234', - to: '5678', - filters: '', - monitorId: undefined, - statusFilter: 'down', - }); - - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(result).toMatchSnapshot(); - }); - - it('returns a down-filtered array for when filtered by up status', async () => { - expect.assertions(2); - const mockEsClient = jest.fn(); - - standardMockResponse.aggregations.timeseries.interval = '1s'; - mockEsClient.mockReturnValue(standardMockResponse); - - const result = await getPingHistogram({ - callES: mockEsClient, - dynamicSettings: DYNAMIC_SETTINGS_DEFAULTS, - from: '1234', - to: '5678', - filters: '', - monitorId: undefined, - statusFilter: 'up', - }); - - expect(mockEsClient).toHaveBeenCalledTimes(1); - expect(result).toMatchSnapshot(); - }); }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts index 299913c8dff08..d33e98c7ba8e7 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_ping_histogram.ts @@ -18,14 +18,12 @@ export interface GetPingHistogramParams { filters?: string | null; /** @member monitorId optional limit to monitorId */ monitorId?: string | null; - /** @member statusFilter special filter targeting the latest status of each monitor */ - statusFilter?: string | null; } export const getPingHistogram: UMElasticsearchQueryFn< GetPingHistogramParams, HistogramResult -> = async ({ callES, dynamicSettings, from, to, filters, monitorId, statusFilter }) => { +> = async ({ callES, dynamicSettings, from, to, filters, monitorId }) => { const boolFilters = filters ? JSON.parse(filters) : null; const additionalFilters = []; if (monitorId) { @@ -81,8 +79,8 @@ export const getPingHistogram: UMElasticsearchQueryFn< const upCount: number = bucket.up.doc_count; return { x, - downCount: statusFilter && statusFilter !== 'down' ? 0 : downCount, - upCount: statusFilter && statusFilter !== 'up' ? 0 : upCount, + downCount, + upCount, y: 1, }; }); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts index 5f8a37cf07028..92295a38cffb4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_snapshot_counts.ts @@ -13,7 +13,6 @@ export interface GetSnapshotCountParams { dateRangeStart: string; dateRangeEnd: string; filters?: string | null; - statusFilter?: string; } export const getSnapshotCount: UMElasticsearchQueryFn = async ({ @@ -22,12 +21,7 @@ export const getSnapshotCount: UMElasticsearchQueryFn => { - if (!(statusFilter === 'up' || statusFilter === 'down' || statusFilter === undefined)) { - throw new Error(`Invalid status filter value '${statusFilter}'`); - } - const context = new QueryContext( callES, heartbeatIndices, @@ -35,18 +29,13 @@ export const getSnapshotCount: UMElasticsearchQueryFn => { diff --git a/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts b/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts index 41078f735920b..a589997889069 100644 --- a/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts +++ b/x-pack/plugins/uptime/server/rest_api/pings/get_ping_histogram.ts @@ -17,12 +17,11 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe dateStart: schema.string(), dateEnd: schema.string(), monitorId: schema.maybe(schema.string()), - statusFilter: schema.maybe(schema.string()), filters: schema.maybe(schema.string()), }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { dateStart, dateEnd, statusFilter, monitorId, filters } = request.query; + const { dateStart, dateEnd, monitorId, filters } = request.query; const result = await libs.requests.getPingHistogram({ callES, @@ -30,7 +29,6 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe from: dateStart, to: dateEnd, monitorId, - statusFilter, filters, }); diff --git a/x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts b/x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts index 7809e102a499f..9502335e4e5a8 100644 --- a/x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts +++ b/x-pack/plugins/uptime/server/rest_api/snapshot/get_snapshot_count.ts @@ -17,18 +17,16 @@ export const createGetSnapshotCount: UMRestApiRouteFactory = (libs: UMServerLibs dateRangeStart: schema.string(), dateRangeEnd: schema.string(), filters: schema.maybe(schema.string()), - statusFilter: schema.maybe(schema.string()), }), }, handler: async ({ callES, dynamicSettings }, _context, request, response): Promise => { - const { dateRangeStart, dateRangeEnd, filters, statusFilter } = request.query; + const { dateRangeStart, dateRangeEnd, filters } = request.query; const result = await libs.requests.getSnapshotCount({ callES, dynamicSettings, dateRangeStart, dateRangeEnd, filters, - statusFilter, }); return response.ok({ body: { diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json deleted file mode 100644 index 27ba69411f88d..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_down.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "total": 7, - "up": 0, - "down": 7 -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json deleted file mode 100644 index 33e60a4340a13..0000000000000 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/snapshot_filtered_by_up.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "total": 10, - "up": 10, - "down": 0 -} \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts b/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts index 9a8951741948e..0d70844650369 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/snapshot.ts @@ -80,23 +80,6 @@ export default function({ getService }: FtrProviderContext) { expectFixtureEql(apiResponse.body, 'snapshot'); }); - - it('will fetch a monitor snapshot filtered by down status', async () => { - const statusFilter = 'down'; - const apiResponse = await supertest.get( - `/api/uptime/snapshot/count?dateRangeStart=${dateRange.start}&dateRangeEnd=${dateRange.end}&statusFilter=${statusFilter}` - ); - - expectFixtureEql(apiResponse.body, 'snapshot_filtered_by_down'); - }); - - it('will fetch a monitor snapshot filtered by up status', async () => { - const statusFilter = 'up'; - const apiResponse = await supertest.get( - `/api/uptime/snapshot/count?dateRangeStart=${dateRange.start}&dateRangeEnd=${dateRange.end}&statusFilter=${statusFilter}` - ); - expectFixtureEql(apiResponse.body, 'snapshot_filtered_by_up'); - }); }); }); }); diff --git a/x-pack/test/functional/apps/uptime/overview.ts b/x-pack/test/functional/apps/uptime/overview.ts index d0dfca64634f6..98d432668a285 100644 --- a/x-pack/test/functional/apps/uptime/overview.ts +++ b/x-pack/test/functional/apps/uptime/overview.ts @@ -10,11 +10,16 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const { uptime } = getPageObjects(['uptime']); const retry = getService('retry'); + const esArchiver = getService('esArchiver'); describe('overview page', function() { const DEFAULT_DATE_START = 'Sep 10, 2019 @ 12:40:08.078'; const DEFAULT_DATE_END = 'Sep 11, 2019 @ 19:40:08.078'; + before(async () => { + await esArchiver.loadIfNeeded('uptime/full_heartbeat'); + }); + beforeEach(async () => { await uptime.goToRoot(); await uptime.setDateRange(DEFAULT_DATE_START, DEFAULT_DATE_END); @@ -159,20 +164,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); describe('snapshot counts', () => { - it('updates the snapshot count when status filter is set to down', async () => { + it('should not update when status filter is set to down', async () => { await uptime.setStatusFilter('down'); await retry.tryForTime(12000, async () => { const counts = await uptime.getSnapshotCount(); - expect(counts).to.eql({ up: '0', down: '7' }); + expect(counts).to.eql({ up: '93', down: '7' }); }); }); - it('updates the snapshot count when status filter is set to up', async () => { + it('should not update when status filter is set to up', async () => { await uptime.setStatusFilter('up'); await retry.tryForTime(12000, async () => { const counts = await uptime.getSnapshotCount(); - expect(counts).to.eql({ up: '93', down: '0' }); + expect(counts).to.eql({ up: '93', down: '7' }); }); }); From 49289785570b176333908f247cbcc977f3364941 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Tue, 5 May 2020 19:14:25 +0200 Subject: [PATCH 13/72] update elastic/charts to 19.2.0 (#65279) --- package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 1f0658bd2a138..b618d8afce7c4 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,7 @@ "@babel/core": "^7.9.0", "@babel/register": "^7.9.0", "@elastic/apm-rum": "^5.1.1", - "@elastic/charts": "19.1.2", + "@elastic/charts": "19.2.0", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", "@elastic/eui": "22.3.0", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index a2248f1ae655e..382b6614fc3ec 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -9,7 +9,7 @@ "kbn:watch": "node scripts/build --watch" }, "dependencies": { - "@elastic/charts": "19.1.2", + "@elastic/charts": "19.2.0", "@elastic/eui": "22.3.0", "@kbn/i18n": "1.0.0", "abortcontroller-polyfill": "^1.4.0", diff --git a/yarn.lock b/yarn.lock index 7c2282fc2915b..b28c5a3212348 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1262,10 +1262,10 @@ dependencies: "@elastic/apm-rum-core" "^5.2.0" -"@elastic/charts@19.1.2": - version "19.1.2" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-19.1.2.tgz#b78730eb11bdcb4fcf17b213411bc48ae9cb770d" - integrity sha512-Qu4Sgp9Uh5Ic7Te3mCi19wlt8qw9Io8+MmCwpeyUi0TeGCPEIrpHp+aL9JkP+qTQJk+oCrJcjeXo2MhzcwOdCw== +"@elastic/charts@19.2.0": + version "19.2.0" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-19.2.0.tgz#45db8c80e4699e5088a1771f190171c1144c5242" + integrity sha512-uhk73OQPaxg7l54gfr+kv+c6jiEngewwH408OySzJbnH23z/5sIpLSziZhV33I6bs/LKDXQSqamC9Jh6Xcwk1A== dependencies: classnames "^2.2.6" d3-array "^1.2.4" From 23282a2f372243530c51935819dfaa8b67240981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 May 2020 13:31:49 -0400 Subject: [PATCH 14/72] Bump jquery from 3.4.1 to 3.5.0 (#64884) --- package.json | 2 +- packages/kbn-ui-framework/package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- .../listing/dashboard_listing_ng_wrapper.html | 2 +- .../public/application/editor/editor.html | 4 ++-- x-pack/package.json | 2 +- .../graph/public/angular/templates/index.html | 2 +- .../angular/templates/listing_ng_wrapper.html | 2 +- .../maps/public/angular/listing_ng_wrapper.html | 2 +- .../monitoring/public/directives/main/index.html | 6 +++--- yarn.lock | 14 +++++++------- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index b618d8afce7c4..f822d452f9cba 100644 --- a/package.json +++ b/package.json @@ -200,7 +200,7 @@ "inert": "^5.1.0", "inline-style": "^2.0.0", "joi": "^13.5.2", - "jquery": "^3.4.1", + "jquery": "^3.5.0", "js-yaml": "3.13.1", "json-stable-stringify": "^1.0.1", "json-stringify-pretty-compact": "1.2.0", diff --git a/packages/kbn-ui-framework/package.json b/packages/kbn-ui-framework/package.json index 5ea031595d1d4..47ed69bc95697 100644 --- a/packages/kbn-ui-framework/package.json +++ b/packages/kbn-ui-framework/package.json @@ -50,7 +50,7 @@ "html": "1.0.0", "html-loader": "^0.5.5", "imports-loader": "^0.8.0", - "jquery": "^3.4.1", + "jquery": "^3.5.0", "keymirror": "0.1.1", "moment": "^2.24.0", "node-sass": "^4.13.1", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 382b6614fc3ec..ae883a5032fe7 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -18,7 +18,7 @@ "core-js": "^3.6.4", "custom-event-polyfill": "^0.3.0", "elasticsearch-browser": "^16.7.0", - "jquery": "^3.4.1", + "jquery": "^3.5.0", "moment": "^2.24.0", "moment-timezone": "^0.5.27", "monaco-editor": "~0.17.0", diff --git a/src/plugins/dashboard/public/application/listing/dashboard_listing_ng_wrapper.html b/src/plugins/dashboard/public/application/listing/dashboard_listing_ng_wrapper.html index f473e91af7ae9..f57c10d1a48dd 100644 --- a/src/plugins/dashboard/public/application/listing/dashboard_listing_ng_wrapper.html +++ b/src/plugins/dashboard/public/application/listing/dashboard_listing_ng_wrapper.html @@ -8,4 +8,4 @@ listing-limit="listingLimit" hide-write-controls="hideWriteControls" initial-filter="initialFilter" -/> +> diff --git a/src/plugins/visualize/public/application/editor/editor.html b/src/plugins/visualize/public/application/editor/editor.html index a031d70ef9a83..3c3455fb34f18 100644 --- a/src/plugins/visualize/public/application/editor/editor.html +++ b/src/plugins/visualize/public/application/editor/editor.html @@ -76,7 +76,7 @@ filters="filters" query="query" app-state="appState" - /> + >

+ > diff --git a/x-pack/package.json b/x-pack/package.json index 5d1fbaa5784e0..5461b21b571f8 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -268,7 +268,7 @@ "io-ts": "^2.0.5", "isbinaryfile": "4.0.2", "joi": "^13.5.2", - "jquery": "^3.4.1", + "jquery": "^3.5.0", "js-search": "^1.4.3", "js-yaml": "3.13.1", "json-stable-stringify": "^1.0.1", diff --git a/x-pack/plugins/graph/public/angular/templates/index.html b/x-pack/plugins/graph/public/angular/templates/index.html index 4493d794cb8d1..8555658596179 100644 --- a/x-pack/plugins/graph/public/angular/templates/index.html +++ b/x-pack/plugins/graph/public/angular/templates/index.html @@ -208,7 +208,7 @@ ng-click="selectSelected(n)"> + ng-click="workspace.deselectNode(n)" > +> diff --git a/x-pack/plugins/maps/public/angular/listing_ng_wrapper.html b/x-pack/plugins/maps/public/angular/listing_ng_wrapper.html index ed787edec6e01..bfea81e13e9df 100644 --- a/x-pack/plugins/maps/public/angular/listing_ng_wrapper.html +++ b/x-pack/plugins/maps/public/angular/listing_ng_wrapper.html @@ -3,4 +3,4 @@ delete="delete" listing-limit="listingLimit" read-only="readOnly" -/> +> diff --git a/x-pack/plugins/monitoring/public/directives/main/index.html b/x-pack/plugins/monitoring/public/directives/main/index.html index f5c4bf5c757af..39d357813b3f2 100644 --- a/x-pack/plugins/monitoring/public/directives/main/index.html +++ b/x-pack/plugins/monitoring/public/directives/main/index.html @@ -240,7 +240,7 @@ i18n-id="xpack.monitoring.logstashNavigation.pipelinesLinkText" i18n-default-message="Pipelines" > - + - + - + Date: Tue, 5 May 2020 19:35:51 +0200 Subject: [PATCH 15/72] Change default icon for the `Log in with Elasticsearch` login selector button. (#65282) --- x-pack/plugins/security/server/config.test.ts | 8 ++++---- x-pack/plugins/security/server/config.ts | 4 ++-- .../security/server/routes/views/login.test.ts | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/security/server/config.test.ts b/x-pack/plugins/security/server/config.test.ts index 2c24864649977..0e1e2e2afeb13 100644 --- a/x-pack/plugins/security/server/config.test.ts +++ b/x-pack/plugins/security/server/config.test.ts @@ -407,7 +407,7 @@ describe('config schema', () => { "basic1": Object { "description": "Log in with Elasticsearch", "enabled": true, - "icon": "logoElastic", + "icon": "logoElasticsearch", "order": 0, "showInSelector": true, }, @@ -467,7 +467,7 @@ describe('config schema', () => { "token1": Object { "description": "Log in with Elasticsearch", "enabled": true, - "icon": "logoElastic", + "icon": "logoElasticsearch", "order": 0, "showInSelector": true, }, @@ -746,14 +746,14 @@ describe('config schema', () => { "basic1": Object { "description": "Log in with Elasticsearch", "enabled": true, - "icon": "logoElastic", + "icon": "logoElasticsearch", "order": 0, "showInSelector": true, }, "basic2": Object { "description": "Log in with Elasticsearch", "enabled": false, - "icon": "logoElastic", + "icon": "logoElasticsearch", "order": 1, "showInSelector": true, }, diff --git a/x-pack/plugins/security/server/config.ts b/x-pack/plugins/security/server/config.ts index 8fe79a788ac51..695653a2ac1db 100644 --- a/x-pack/plugins/security/server/config.ts +++ b/x-pack/plugins/security/server/config.ts @@ -62,7 +62,7 @@ const providersConfigSchema = schema.object( defaultMessage: 'Log in with Elasticsearch', }), }), - icon: schema.string({ defaultValue: 'logoElastic' }), + icon: schema.string({ defaultValue: 'logoElasticsearch' }), showInSelector: schema.boolean({ defaultValue: true, validate: value => { @@ -78,7 +78,7 @@ const providersConfigSchema = schema.object( defaultMessage: 'Log in with Elasticsearch', }), }), - icon: schema.string({ defaultValue: 'logoElastic' }), + icon: schema.string({ defaultValue: 'logoElasticsearch' }), showInSelector: schema.boolean({ defaultValue: true, validate: value => { diff --git a/x-pack/plugins/security/server/routes/views/login.test.ts b/x-pack/plugins/security/server/routes/views/login.test.ts index 014ad390a3d53..5c41a48bf5ee4 100644 --- a/x-pack/plugins/security/server/routes/views/login.test.ts +++ b/x-pack/plugins/security/server/routes/views/login.test.ts @@ -252,7 +252,7 @@ describe('Login view routes', () => { name: 'basic1', type: 'basic', usesLoginForm: true, - icon: 'logoElastic', + icon: 'logoElasticsearch', description: 'Log in with Elasticsearch', }, ], @@ -264,7 +264,7 @@ describe('Login view routes', () => { name: 'token1', type: 'token', usesLoginForm: true, - icon: 'logoElastic', + icon: 'logoElasticsearch', description: 'Log in with Elasticsearch', }, ], @@ -309,7 +309,7 @@ describe('Login view routes', () => { name: 'basic1', type: 'basic', usesLoginForm: true, - icon: 'logoElastic', + icon: 'logoElasticsearch', description: 'Log in with Elasticsearch', }, ], @@ -325,7 +325,7 @@ describe('Login view routes', () => { name: 'basic1', type: 'basic', usesLoginForm: true, - icon: 'logoElastic', + icon: 'logoElasticsearch', description: 'Log in with Elasticsearch', }, ], @@ -340,7 +340,7 @@ describe('Login view routes', () => { order: 0, description: 'some-desc1', hint: 'some-hint1', - icon: 'logoElastic', + icon: 'logoElasticsearch', }, }, saml: { @@ -355,7 +355,7 @@ describe('Login view routes', () => { name: 'basic1', description: 'some-desc1', hint: 'some-hint1', - icon: 'logoElastic', + icon: 'logoElasticsearch', usesLoginForm: true, }, { From 399eed77bb591bbb5fce9799dc4798fd29561f64 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Tue, 5 May 2020 19:49:39 +0200 Subject: [PATCH 16/72] [APM] Annotations API (#64796) --- x-pack/plugins/apm/common/annotations.ts | 2 +- x-pack/plugins/apm/kibana.json | 6 +- .../charts/CustomPlot/AnnotationsPlot.tsx | 6 +- .../apm/public/context/ChartsSyncContext.tsx | 2 +- .../scripts/optimize-tsconfig/tsconfig.json | 1 + .../lib/helpers/create_or_update_index.ts | 105 ----- .../apm/server/lib/helpers/es_client.ts | 8 +- .../get_derived_service_annotations.ts | 111 +++++ .../annotations/get_stored_annotations.ts | 76 ++++ .../lib/services/annotations/index.test.ts | 42 +- .../server/lib/services/annotations/index.ts | 129 ++---- .../create_agent_config_index.ts | 15 +- .../delete_configuration.ts | 2 +- .../get_environments/index.ts | 2 +- .../agent_configuration/get_service_names.ts | 2 +- .../list_configurations.ts | 2 +- .../settings/apm_indices/get_apm_indices.ts | 2 +- .../custom_link/create_custom_link_index.ts | 15 +- .../custom_link/delete_custom_link.ts | 2 +- .../apm/server/lib/traces/get_trace.ts | 2 +- .../server/lib/transaction_groups/fetcher.ts | 2 +- .../server/lib/transaction_groups/index.ts | 2 +- .../avg_duration_by_browser/fetcher.ts | 2 +- .../charts/get_anomaly_data/fetcher.ts | 2 +- .../charts/get_anomaly_data/index.test.ts | 2 +- .../charts/get_timeseries_data/fetcher.ts | 2 +- .../server/lib/transactions/charts/index.ts | 2 +- .../distribution/get_buckets/transform.ts | 2 +- .../lib/transactions/distribution/index.ts | 2 +- .../lib/ui_filters/local_ui_filters/index.ts | 2 +- x-pack/plugins/apm/server/plugin.ts | 3 + .../apm/server/routes/create_api/index.ts | 4 +- .../apm/server/routes/create_apm_api.ts | 4 +- x-pack/plugins/apm/server/routes/services.ts | 72 +++- x-pack/plugins/apm/server/routes/typings.ts | 3 + .../observability/common/annotations.ts | 51 +++ x-pack/plugins/observability/kibana.json | 8 +- x-pack/plugins/observability/server/index.ts | 33 ++ .../lib/annotations/bootstrap_annotations.ts | 42 ++ .../annotations/create_annotations_client.ts | 106 +++++ .../server/lib/annotations/mappings.ts | 47 +++ .../annotations/register_annotation_apis.ts | 109 +++++ x-pack/plugins/observability/server/plugin.ts | 59 +++ .../server/utils/create_or_update_index.ts | 108 +++++ .../plugins/observability/typings/common.ts | 9 + .../api_integration/apis/apm/annotations.ts | 389 ++++++++++++++++++ .../apis/apm/feature_controls.ts | 2 +- x-pack/test/api_integration/apis/apm/index.ts | 1 + x-pack/test/api_integration/apis/index.js | 1 + .../apis/observability/annotations.ts | 290 +++++++++++++ .../apis/observability/index.ts | 13 + 51 files changed, 1640 insertions(+), 266 deletions(-) delete mode 100644 x-pack/plugins/apm/server/lib/helpers/create_or_update_index.ts create mode 100644 x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts create mode 100644 x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts create mode 100644 x-pack/plugins/observability/common/annotations.ts create mode 100644 x-pack/plugins/observability/server/index.ts create mode 100644 x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts create mode 100644 x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts create mode 100644 x-pack/plugins/observability/server/lib/annotations/mappings.ts create mode 100644 x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts create mode 100644 x-pack/plugins/observability/server/plugin.ts create mode 100644 x-pack/plugins/observability/server/utils/create_or_update_index.ts create mode 100644 x-pack/plugins/observability/typings/common.ts create mode 100644 x-pack/test/api_integration/apis/apm/annotations.ts create mode 100644 x-pack/test/api_integration/apis/observability/annotations.ts create mode 100644 x-pack/test/api_integration/apis/observability/index.ts diff --git a/x-pack/plugins/apm/common/annotations.ts b/x-pack/plugins/apm/common/annotations.ts index 33122f55d8800..264236e22b0c1 100644 --- a/x-pack/plugins/apm/common/annotations.ts +++ b/x-pack/plugins/apm/common/annotations.ts @@ -11,6 +11,6 @@ export enum AnnotationType { export interface Annotation { type: AnnotationType; id: string; - time: number; + '@timestamp': number; text: string; } diff --git a/x-pack/plugins/apm/kibana.json b/x-pack/plugins/apm/kibana.json index 85e3761129018..7c267efedf1af 100644 --- a/x-pack/plugins/apm/kibana.json +++ b/x-pack/plugins/apm/kibana.json @@ -16,9 +16,13 @@ "taskManager", "actions", "alerting", + "observability", "security" ], "server": true, "ui": true, - "configPath": ["xpack", "apm"] + "configPath": [ + "xpack", + "apm" + ] } diff --git a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/AnnotationsPlot.tsx b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/AnnotationsPlot.tsx index 6eff4759b2e7c..0233282bad1b5 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/AnnotationsPlot.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/CustomPlot/AnnotationsPlot.tsx @@ -34,7 +34,7 @@ const style = { export function AnnotationsPlot(props: Props) { const { plotValues, annotations } = props; - const tickValues = annotations.map(annotation => annotation.time); + const tickValues = annotations.map(annotation => annotation['@timestamp']); return ( <> @@ -46,12 +46,12 @@ export function AnnotationsPlot(props: Props) { key={annotation.id} style={{ position: 'absolute', - left: plotValues.x(annotation.time) - 8, + left: plotValues.x(annotation['@timestamp']) - 8, top: -2 }} > diff --git a/x-pack/plugins/apm/public/context/ChartsSyncContext.tsx b/x-pack/plugins/apm/public/context/ChartsSyncContext.tsx index afce0811b48f6..065e0b8733122 100644 --- a/x-pack/plugins/apm/public/context/ChartsSyncContext.tsx +++ b/x-pack/plugins/apm/public/context/ChartsSyncContext.tsx @@ -28,7 +28,7 @@ const ChartsSyncContextProvider: React.FC = ({ children }) => { callApmApi => { if (start && end && serviceName) { return callApmApi({ - pathname: '/api/apm/services/{serviceName}/annotations', + pathname: '/api/apm/services/{serviceName}/annotation/search', params: { path: { serviceName diff --git a/x-pack/plugins/apm/scripts/optimize-tsconfig/tsconfig.json b/x-pack/plugins/apm/scripts/optimize-tsconfig/tsconfig.json index 5e05d3962eccb..34b67c834554d 100644 --- a/x-pack/plugins/apm/scripts/optimize-tsconfig/tsconfig.json +++ b/x-pack/plugins/apm/scripts/optimize-tsconfig/tsconfig.json @@ -1,6 +1,7 @@ { "include": [ "./plugins/apm/**/*", + "./plugins/observability/**/*", "./typings/**/*" ], "exclude": [ diff --git a/x-pack/plugins/apm/server/lib/helpers/create_or_update_index.ts b/x-pack/plugins/apm/server/lib/helpers/create_or_update_index.ts deleted file mode 100644 index 4df02786b1fb5..0000000000000 --- a/x-pack/plugins/apm/server/lib/helpers/create_or_update_index.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import pRetry from 'p-retry'; -import { IClusterClient, Logger } from 'src/core/server'; -import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; - -export type Mappings = - | { - dynamic?: boolean | 'strict'; - properties: Record; - dynamic_templates?: any[]; - } - | { - type: string; - ignore_above?: number; - scaling_factor?: number; - ignore_malformed?: boolean; - coerce?: boolean; - fields?: Record; - }; - -export async function createOrUpdateIndex({ - index, - mappings, - esClient, - logger -}: { - index: string; - mappings: Mappings; - esClient: IClusterClient; - logger: Logger; -}) { - try { - /* - * In some cases we could be trying to create an index before ES is ready. - * When this happens, we retry creating the index with exponential backoff. - * We use retry's default formula, meaning that the first retry happens after 2s, - * the 5th after 32s, and the final attempt after around 17m. If the final attempt fails, - * the error is logged to the console. - * See https://github.com/sindresorhus/p-retry and https://github.com/tim-kos/node-retry. - */ - await pRetry(async () => { - const { callAsInternalUser } = esClient; - const indexExists = await callAsInternalUser('indices.exists', { index }); - const result = indexExists - ? await updateExistingIndex({ - index, - callAsInternalUser, - mappings - }) - : await createNewIndex({ - index, - callAsInternalUser, - mappings - }); - - if (!result.acknowledged) { - const resultError = - result && result.error && JSON.stringify(result.error); - throw new Error(resultError); - } - }); - } catch (e) { - logger.error( - `Could not create APM index: '${index}'. Error: ${e.message}.` - ); - } -} - -function createNewIndex({ - index, - callAsInternalUser, - mappings -}: { - index: string; - callAsInternalUser: CallCluster; - mappings: Mappings; -}) { - return callAsInternalUser('indices.create', { - index, - body: { - // auto_expand_replicas: Allows cluster to not have replicas for this index - settings: { 'index.auto_expand_replicas': '0-1' }, - mappings - } - }); -} - -function updateExistingIndex({ - index, - callAsInternalUser, - mappings -}: { - index: string; - callAsInternalUser: CallCluster; - mappings: Mappings; -}) { - return callAsInternalUser('indices.putMapping', { - index, - body: mappings - }); -} diff --git a/x-pack/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/plugins/apm/server/lib/helpers/es_client.ts index 45a7eca46caba..5d3cd9464af71 100644 --- a/x-pack/plugins/apm/server/lib/helpers/es_client.ts +++ b/x-pack/plugins/apm/server/lib/helpers/es_client.ts @@ -7,10 +7,10 @@ /* eslint-disable no-console */ import { IndexDocumentParams, - IndicesDeleteParams, SearchParams, IndicesCreateParams, - DeleteDocumentResponse + DeleteDocumentResponse, + DeleteDocumentParams } from 'elasticsearch'; import { cloneDeep, isString, merge } from 'lodash'; import { KibanaRequest } from 'src/core/server'; @@ -204,7 +204,9 @@ export function getESClient( index: (params: APMIndexDocumentParams) => { return callEs('index', params); }, - delete: (params: IndicesDeleteParams): Promise => { + delete: ( + params: Omit + ): Promise => { return callEs('delete', params); }, indicesCreate: (params: IndicesCreateParams) => { diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts new file mode 100644 index 0000000000000..e1f24bc1443f0 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts @@ -0,0 +1,111 @@ +/* + * 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 { isNumber } from 'lodash'; +import { Annotation, AnnotationType } from '../../../../common/annotations'; +import { SetupTimeRange, Setup } from '../../helpers/setup_request'; +import { ESFilter } from '../../../../typings/elasticsearch'; +import { rangeFilter } from '../../helpers/range_filter'; +import { + PROCESSOR_EVENT, + SERVICE_NAME, + SERVICE_VERSION +} from '../../../../common/elasticsearch_fieldnames'; +import { getEnvironmentUiFilterES } from '../../helpers/convert_ui_filters/get_environment_ui_filter_es'; + +export async function getDerivedServiceAnnotations({ + setup, + serviceName, + environment +}: { + serviceName: string; + environment?: string; + setup: Setup & SetupTimeRange; +}) { + const { start, end, client, indices } = setup; + + const filter: ESFilter[] = [ + { term: { [PROCESSOR_EVENT]: 'transaction' } }, + { term: { [SERVICE_NAME]: serviceName } } + ]; + + const environmentFilter = getEnvironmentUiFilterES(environment); + + if (environmentFilter) { + filter.push(environmentFilter); + } + + const versions = + ( + await client.search({ + index: indices['apm_oss.transactionIndices'], + body: { + size: 0, + query: { + bool: { + filter: filter.concat({ range: rangeFilter(start, end) }) + } + }, + aggs: { + versions: { + terms: { + field: SERVICE_VERSION + } + } + } + } + }) + ).aggregations?.versions.buckets.map(bucket => bucket.key) ?? []; + + if (versions.length <= 1) { + return []; + } + const annotations = await Promise.all( + versions.map(async version => { + const response = await client.search({ + index: indices['apm_oss.transactionIndices'], + body: { + size: 0, + query: { + bool: { + filter: filter.concat({ + term: { + [SERVICE_VERSION]: version + } + }) + } + }, + aggs: { + first_seen: { + min: { + field: '@timestamp' + } + } + } + } + }); + + const firstSeen = response.aggregations?.first_seen.value; + + if (!isNumber(firstSeen)) { + throw new Error( + 'First seen for version was unexpectedly undefined or null.' + ); + } + + if (firstSeen < start || firstSeen > end) { + return null; + } + + return { + type: AnnotationType.VERSION, + id: version, + '@timestamp': firstSeen, + text: version + }; + }) + ); + return annotations.filter(Boolean) as Annotation[]; +} diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts new file mode 100644 index 0000000000000..44aa554fa320a --- /dev/null +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts @@ -0,0 +1,76 @@ +/* + * 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 { APICaller } from 'kibana/server'; +import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; +import { ESSearchResponse } from '../../../../typings/elasticsearch'; +import { ScopedAnnotationsClient } from '../../../../../observability/server'; +import { Annotation, AnnotationType } from '../../../../common/annotations'; +import { Annotation as ESAnnotation } from '../../../../../observability/common/annotations'; +import { SetupTimeRange, Setup } from '../../helpers/setup_request'; +import { getEnvironmentUiFilterES } from '../../helpers/convert_ui_filters/get_environment_ui_filter_es'; + +export async function getStoredAnnotations({ + setup, + serviceName, + environment, + apiCaller, + annotationsClient +}: { + setup: Setup & SetupTimeRange; + serviceName: string; + environment?: string; + apiCaller: APICaller; + annotationsClient: ScopedAnnotationsClient; +}): Promise { + try { + const environmentFilter = getEnvironmentUiFilterES(environment); + + const response: ESSearchResponse = (await apiCaller( + 'search', + { + index: annotationsClient.index, + body: { + size: 50, + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: setup.start, + lt: setup.end + } + } + }, + { term: { 'annotation.type': 'deployment' } }, + { term: { tags: 'apm' } }, + { term: { [SERVICE_NAME]: serviceName } }, + ...(environmentFilter ? [environmentFilter] : []) + ] + } + } + } + } + )) as any; + + return response.hits.hits.map(hit => { + return { + type: AnnotationType.VERSION, + id: hit._id, + '@timestamp': new Date(hit._source['@timestamp']).getTime(), + text: hit._source.message + }; + }); + } catch (error) { + // index is only created when an annotation has been indexed, + // so we should handle this error gracefully + if (error.body?.error?.type === 'index_not_found_exception') { + return []; + } + throw error; + } +} diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts b/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts index 614014ee37afc..ef70a29728e75 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/index.test.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { getServiceAnnotations } from '.'; +import { getDerivedServiceAnnotations } from './get_derived_service_annotations'; import { SearchParamsMock, inspectSearchParams @@ -24,7 +24,7 @@ describe('getServiceAnnotations', () => { it('returns no annotations', async () => { mock = await inspectSearchParams( setup => - getServiceAnnotations({ + getDerivedServiceAnnotations({ setup, serviceName: 'foo', environment: 'bar' @@ -34,7 +34,7 @@ describe('getServiceAnnotations', () => { } ); - expect(mock.response).toEqual({ annotations: [] }); + expect(mock.response).toEqual([]); }); }); @@ -42,7 +42,7 @@ describe('getServiceAnnotations', () => { it('returns no annotations', async () => { mock = await inspectSearchParams( setup => - getServiceAnnotations({ + getDerivedServiceAnnotations({ setup, serviceName: 'foo', environment: 'bar' @@ -52,7 +52,7 @@ describe('getServiceAnnotations', () => { } ); - expect(mock.response).toEqual({ annotations: [] }); + expect(mock.response).toEqual([]); }); }); @@ -65,7 +65,7 @@ describe('getServiceAnnotations', () => { ]; mock = await inspectSearchParams( setup => - getServiceAnnotations({ + getDerivedServiceAnnotations({ setup, serviceName: 'foo', environment: 'bar' @@ -77,22 +77,20 @@ describe('getServiceAnnotations', () => { expect(mock.spy.mock.calls.length).toBe(3); - expect(mock.response).toEqual({ - annotations: [ - { - id: '8.0.0', - text: '8.0.0', - time: 1.5281138e12, - type: 'version' - }, - { - id: '7.5.0', - text: '7.5.0', - time: 1.5281138e12, - type: 'version' - } - ] - }); + expect(mock.response).toEqual([ + { + id: '8.0.0', + text: '8.0.0', + '@timestamp': 1.5281138e12, + type: 'version' + }, + { + id: '7.5.0', + text: '7.5.0', + '@timestamp': 1.5281138e12, + type: 'version' + } + ]); }); }); }); diff --git a/x-pack/plugins/apm/server/lib/services/annotations/index.ts b/x-pack/plugins/apm/server/lib/services/annotations/index.ts index c03746ca220ee..40e7eb6535935 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/index.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/index.ts @@ -3,112 +3,51 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { isNumber } from 'lodash'; -import { Annotation, AnnotationType } from '../../../../common/annotations'; -import { ESFilter } from '../../../../typings/elasticsearch'; -import { - SERVICE_NAME, - SERVICE_ENVIRONMENT, - PROCESSOR_EVENT -} from '../../../../common/elasticsearch_fieldnames'; +import { APICaller } from 'kibana/server'; +import { ScopedAnnotationsClient } from '../../../../../observability/server'; +import { getDerivedServiceAnnotations } from './get_derived_service_annotations'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; -import { rangeFilter } from '../../helpers/range_filter'; -import { SERVICE_VERSION } from '../../../../common/elasticsearch_fieldnames'; +import { getStoredAnnotations } from './get_stored_annotations'; export async function getServiceAnnotations({ setup, serviceName, - environment + environment, + annotationsClient, + apiCaller }: { serviceName: string; environment?: string; setup: Setup & SetupTimeRange; + annotationsClient?: ScopedAnnotationsClient; + apiCaller: APICaller; }) { - const { start, end, client, indices } = setup; - - const filter: ESFilter[] = [ - { term: { [PROCESSOR_EVENT]: 'transaction' } }, - { range: rangeFilter(start, end) }, - { term: { [SERVICE_NAME]: serviceName } } - ]; - - if (environment) { - filter.push({ term: { [SERVICE_ENVIRONMENT]: environment } }); - } - - const versions = - ( - await client.search({ - index: indices['apm_oss.transactionIndices'], - body: { - size: 0, - track_total_hits: false, - query: { - bool: { - filter - } - }, - aggs: { - versions: { - terms: { - field: SERVICE_VERSION - } - } - } - } + // start fetching derived annotations (based on transactions), but don't wait on it + // it will likely be significantly slower than the stored annotations + const derivedAnnotationsPromise = getDerivedServiceAnnotations({ + setup, + serviceName, + environment + }); + + const storedAnnotations = annotationsClient + ? await getStoredAnnotations({ + setup, + serviceName, + environment, + annotationsClient, + apiCaller }) - ).aggregations?.versions.buckets.map(bucket => bucket.key) ?? []; - - if (versions.length > 1) { - const annotations = await Promise.all( - versions.map(async version => { - const response = await client.search({ - index: indices['apm_oss.transactionIndices'], - body: { - size: 0, - query: { - bool: { - filter: filter - .filter(esFilter => !Object.keys(esFilter).includes('range')) - .concat({ - term: { - [SERVICE_VERSION]: version - } - }) - } - }, - aggs: { - first_seen: { - min: { - field: '@timestamp' - } - } - }, - track_total_hits: false - } - }); + : []; - const firstSeen = response.aggregations?.first_seen.value; - - if (!isNumber(firstSeen)) { - throw new Error( - 'First seen for version was unexpectedly undefined or null.' - ); - } - - if (firstSeen < start || firstSeen > end) { - return null; - } - - return { - type: AnnotationType.VERSION, - id: version, - time: firstSeen, - text: version - }; - }) - ); - return { annotations: annotations.filter(Boolean) as Annotation[] }; + if (storedAnnotations.length) { + derivedAnnotationsPromise.catch(error => { + // handle error silently to prevent Kibana from crashing + }); + return { annotations: storedAnnotations }; } - return { annotations: [] }; + + return { + annotations: await derivedAnnotationsPromise + }; } diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts index b2dc22ceb2918..356863c5f6e1e 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts @@ -5,11 +5,11 @@ */ import { IClusterClient, Logger } from 'src/core/server'; -import { APMConfig } from '../../..'; import { createOrUpdateIndex, - Mappings -} from '../../helpers/create_or_update_index'; + MappingsDefinition +} from '../../../../../observability/server'; +import { APMConfig } from '../../..'; import { getApmIndicesConfig } from '../apm_indices/get_apm_indices'; export async function createApmAgentConfigurationIndex({ @@ -22,10 +22,15 @@ export async function createApmAgentConfigurationIndex({ logger: Logger; }) { const index = getApmIndicesConfig(config).apmAgentConfigurationIndex; - return createOrUpdateIndex({ index, esClient, logger, mappings }); + return createOrUpdateIndex({ + index, + apiCaller: esClient.callAsInternalUser, + logger, + mappings + }); } -const mappings: Mappings = { +const mappings: MappingsDefinition = { dynamic: 'strict', dynamic_templates: [ { diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts index 293c01d4b61d5..be5f9f342557d 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts @@ -16,7 +16,7 @@ export async function deleteConfiguration({ const { internalClient, indices } = setup; const params = { - refresh: 'wait_for', + refresh: 'wait_for' as const, index: indices.apmAgentConfigurationIndex, id: configurationId }; diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts index c05b4e113deb5..2e3e4ae7e22ed 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_environments/index.ts @@ -6,7 +6,7 @@ import { getAllEnvironments } from './get_all_environments'; import { Setup } from '../../../helpers/setup_request'; -import { PromiseReturnType } from '../../../../../typings/common'; +import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { getExistingEnvironmentsForService } from './get_existing_environments_for_service'; export type AgentConfigurationEnvironmentsAPIResponse = PromiseReturnType< diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts index 352bbe1b6a294..316a9551d992f 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts @@ -5,7 +5,7 @@ */ import { Setup } from '../../helpers/setup_request'; -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { PROCESSOR_EVENT, SERVICE_NAME diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts index c44d7b41f532b..357d0e7487e1c 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { Setup } from '../../helpers/setup_request'; import { AgentConfiguration } from '../../../../common/agent_configuration/configuration_types'; import { convertConfigSettingsToString } from './convert_settings_to_string'; diff --git a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts b/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts index f338ee058842c..5ee1f36cbac52 100644 --- a/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts +++ b/x-pack/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts @@ -7,7 +7,7 @@ import { merge } from 'lodash'; import { Server } from 'hapi'; import { SavedObjectsClient } from 'src/core/server'; -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { APM_INDICES_SAVED_OBJECT_TYPE, APM_INDICES_SAVED_OBJECT_ID diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts index 42b99b34beea7..bc0af3b0bb254 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts @@ -5,11 +5,11 @@ */ import { IClusterClient, Logger } from 'src/core/server'; -import { APMConfig } from '../../..'; import { createOrUpdateIndex, - Mappings -} from '../../helpers/create_or_update_index'; + MappingsDefinition +} from '../../../../../observability/server'; +import { APMConfig } from '../../..'; import { getApmIndicesConfig } from '../apm_indices/get_apm_indices'; export const createApmCustomLinkIndex = async ({ @@ -22,10 +22,15 @@ export const createApmCustomLinkIndex = async ({ logger: Logger; }) => { const index = getApmIndicesConfig(config).apmCustomLinkIndex; - return createOrUpdateIndex({ index, esClient, logger, mappings }); + return createOrUpdateIndex({ + index, + apiCaller: esClient.callAsInternalUser, + logger, + mappings + }); }; -const mappings: Mappings = { +const mappings: MappingsDefinition = { dynamic: 'strict', properties: { '@timestamp': { diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts index 2f3ea0940cb26..215c30b9581ff 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/delete_custom_link.ts @@ -16,7 +16,7 @@ export async function deleteCustomLink({ const { internalClient, indices } = setup; const params = { - refresh: 'wait_for', + refresh: 'wait_for' as const, index: indices.apmCustomLinkIndex, id: customLinkId }; diff --git a/x-pack/plugins/apm/server/lib/traces/get_trace.ts b/x-pack/plugins/apm/server/lib/traces/get_trace.ts index a1b9270e0d7b3..6d0a3e0a758e1 100644 --- a/x-pack/plugins/apm/server/lib/traces/get_trace.ts +++ b/x-pack/plugins/apm/server/lib/traces/get_trace.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PromiseReturnType } from '../../../typings/common'; +import { PromiseReturnType } from '../../../../observability/typings/common'; import { Setup, SetupTimeRange } from '../helpers/setup_request'; import { getTraceItems } from './get_trace_items'; diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index fb1aafc2d6c95..18f0726ae4061 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -12,7 +12,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { getTransactionGroupsProjection } from '../../../common/projections/transaction_groups'; import { mergeProjection } from '../../../common/projections/util/merge_projection'; -import { PromiseReturnType } from '../../../typings/common'; +import { PromiseReturnType } from '../../../../observability/typings/common'; import { SortOptions } from '../../../typings/elasticsearch/aggregations'; import { Transaction } from '../../../typings/es_schemas/ui/transaction'; import { diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/index.ts b/x-pack/plugins/apm/server/lib/transaction_groups/index.ts index 3656b32c17092..37b61b494297f 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/index.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/index.ts @@ -11,7 +11,7 @@ import { } from '../helpers/setup_request'; import { transactionGroupsFetcher, Options } from './fetcher'; import { transactionGroupsTransformer } from './transform'; -import { PromiseReturnType } from '../../../typings/common'; +import { PromiseReturnType } from '../../../../observability/typings/common'; export type TransactionGroupListAPIResponse = PromiseReturnType< typeof getTransactionGroupList diff --git a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts index 8a96a25aef50e..b36ae8961806b 100644 --- a/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/avg_duration_by_browser/fetcher.ts @@ -5,7 +5,7 @@ */ import { ESFilter } from '../../../../typings/elasticsearch'; -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { PROCESSOR_EVENT, SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts index 5f211b1427259..a0b6bf40eea61 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/fetcher.ts @@ -5,7 +5,7 @@ */ import { getMlIndex } from '../../../../../common/ml_job_constants'; -import { PromiseReturnType } from '../../../../../typings/common'; +import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { Setup, SetupTimeRange } from '../../../helpers/setup_request'; export type ESResponse = Exclude< diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts index 7a3277965ef8e..94dd4860883bd 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts @@ -7,7 +7,7 @@ import { getAnomalySeries } from '.'; import { mlAnomalyResponse } from './mock_responses/ml_anomaly_response'; import { mlBucketSpanResponse } from './mock_responses/ml_bucket_span_response'; -import { PromiseReturnType } from '../../../../../typings/common'; +import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { APMConfig } from '../../../..'; describe('getAnomalySeries', () => { diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index e33b98592da2d..8d37cfa05e951 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -13,7 +13,7 @@ import { TRANSACTION_RESULT, TRANSACTION_TYPE } from '../../../../../common/elasticsearch_fieldnames'; -import { PromiseReturnType } from '../../../../../typings/common'; +import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { getBucketSize } from '../../../helpers/get_bucket_size'; import { rangeFilter } from '../../../helpers/range_filter'; import { diff --git a/x-pack/plugins/apm/server/lib/transactions/charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/charts/index.ts index a6a1a76e19664..45e9bb0db3c3b 100644 --- a/x-pack/plugins/apm/server/lib/transactions/charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/charts/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { Setup, SetupTimeRange, diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts index 9b22e1794f969..6d3e5d12e87cb 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/get_buckets/transform.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PromiseReturnType } from '../../../../../typings/common'; +import { PromiseReturnType } from '../../../../../../observability/typings/common'; import { Transaction } from '../../../../../typings/es_schemas/ui/transaction'; import { bucketFetcher } from './fetcher'; diff --git a/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts b/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts index 9dd29a0664329..d304a2a8a563b 100644 --- a/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/distribution/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { Setup, SetupTimeRange, diff --git a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts index 1462cf2eeefa4..c069113e549f1 100644 --- a/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts +++ b/x-pack/plugins/apm/server/lib/ui_filters/local_ui_filters/index.ts @@ -6,7 +6,7 @@ import { cloneDeep, sortByOrder } from 'lodash'; import { UIFilters } from '../../../../typings/ui_filters'; import { Projection } from '../../../../common/projections/typings'; -import { PromiseReturnType } from '../../../../typings/common'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; import { getLocalFilterQuery } from './get_local_filter_query'; import { Setup } from '../../helpers/setup_request'; import { localUIFilters, LocalUIFilterName } from './config'; diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 29ab618cbdd0a..b17bffea812fc 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -12,6 +12,7 @@ import { } from 'src/core/server'; import { Observable, combineLatest } from 'rxjs'; import { map, take } from 'rxjs/operators'; +import { ObservabilityPluginSetup } from '../../observability/server'; import { SecurityPluginSetup } from '../../security/public'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { TaskManagerSetupContract } from '../../task_manager/server'; @@ -57,6 +58,7 @@ export class APMPlugin implements Plugin { taskManager?: TaskManagerSetupContract; alerting?: AlertingPlugin['setup']; actions?: ActionsPlugin['setup']; + observability?: ObservabilityPluginSetup; features: FeaturesPluginSetup; security?: SecurityPluginSetup; } @@ -114,6 +116,7 @@ export class APMPlugin implements Plugin { config$: mergedConfig$, logger: this.logger!, plugins: { + observability: plugins.observability, security: plugins.security } }); diff --git a/x-pack/plugins/apm/server/routes/create_api/index.ts b/x-pack/plugins/apm/server/routes/create_api/index.ts index 9b611a0bbd6bc..53c3630d5a743 100644 --- a/x-pack/plugins/apm/server/routes/create_api/index.ts +++ b/x-pack/plugins/apm/server/routes/create_api/index.ts @@ -136,13 +136,13 @@ export function createApi() { request, context: { ...context, + plugins, // Only return values for parameters that have runtime types, // but always include query as _debug is always set even if // it's not defined in the route. params: pick(parsedParams, ...Object.keys(params), 'query'), config, - logger, - plugins + logger } }); diff --git a/x-pack/plugins/apm/server/routes/create_apm_api.ts b/x-pack/plugins/apm/server/routes/create_apm_api.ts index 7964d8b0268e8..4fd740c4e81c1 100644 --- a/x-pack/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/plugins/apm/server/routes/create_apm_api.ts @@ -19,7 +19,8 @@ import { serviceTransactionTypesRoute, servicesRoute, serviceNodeMetadataRoute, - serviceAnnotationsRoute + serviceAnnotationsRoute, + serviceAnnotationsCreateRoute } from './services'; import { agentConfigurationRoute, @@ -87,6 +88,7 @@ const createApmApi = () => { .add(servicesRoute) .add(serviceNodeMetadataRoute) .add(serviceAnnotationsRoute) + .add(serviceAnnotationsCreateRoute) // Agent configuration .add(getSingleAgentConfigurationRoute) diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index 1c6561ee24c93..474ab1c6082a4 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -5,6 +5,9 @@ */ import * as t from 'io-ts'; +import Boom from 'boom'; +import { unique } from 'lodash'; +import { ScopedAnnotationsClient } from '../../../observability/server'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceAgentName } from '../lib/services/get_service_agent_name'; import { getServices } from '../lib/services/get_services'; @@ -13,6 +16,7 @@ import { getServiceNodeMetadata } from '../lib/services/get_service_node_metadat import { createRoute } from './create_route'; import { uiFiltersRt, rangeRt } from './default_api_types'; import { getServiceAnnotations } from '../lib/services/annotations'; +import { dateAsStringRt } from '../../common/runtime_types/date_as_string_rt'; export const servicesRoute = createRoute(core => ({ path: '/api/apm/services', @@ -74,7 +78,7 @@ export const serviceNodeMetadataRoute = createRoute(() => ({ })); export const serviceAnnotationsRoute = createRoute(() => ({ - path: '/api/apm/services/{serviceName}/annotations', + path: '/api/apm/services/{serviceName}/annotation/search', params: { path: t.type({ serviceName: t.string @@ -91,10 +95,74 @@ export const serviceAnnotationsRoute = createRoute(() => ({ const { serviceName } = context.params.path; const { environment } = context.params.query; + let annotationsClient: ScopedAnnotationsClient | undefined; + + if (context.plugins.observability) { + annotationsClient = await context.plugins.observability.getScopedAnnotationsClient( + request + ); + } + return getServiceAnnotations({ setup, serviceName, - environment + environment, + annotationsClient, + apiCaller: context.core.elasticsearch.dataClient.callAsCurrentUser + }); + } +})); + +export const serviceAnnotationsCreateRoute = createRoute(() => ({ + path: '/api/apm/services/{serviceName}/annotation', + method: 'POST', + options: { + tags: ['access:apm', 'access:apm_write'] + }, + params: { + path: t.type({ + serviceName: t.string + }), + body: t.intersection([ + t.type({ + '@timestamp': dateAsStringRt, + service: t.intersection([ + t.type({ + version: t.string + }), + t.partial({ + environment: t.string + }) + ]) + }), + t.partial({ + message: t.string, + tags: t.array(t.string) + }) + ]) + }, + handler: async ({ request, context }) => { + const annotationsClient = await context.plugins.observability?.getScopedAnnotationsClient( + request + ); + + if (!annotationsClient) { + throw Boom.notFound(); + } + + const { body, path } = context.params; + + return annotationsClient.create({ + message: body.service.version, + ...body, + annotation: { + type: 'deployment' + }, + service: { + ...body.service, + name: path.serviceName + }, + tags: unique(['apm'].concat(body.tags ?? [])) }); } })); diff --git a/x-pack/plugins/apm/server/routes/typings.ts b/x-pack/plugins/apm/server/routes/typings.ts index e049255eb8ec8..fe6195605fb2a 100644 --- a/x-pack/plugins/apm/server/routes/typings.ts +++ b/x-pack/plugins/apm/server/routes/typings.ts @@ -14,6 +14,7 @@ import { import { PickByValue, Optional } from 'utility-types'; import { Observable } from 'rxjs'; import { Server } from 'hapi'; +import { ObservabilityPluginSetup } from '../../../observability/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { FetchOptions } from '../../public/services/rest/callApi'; import { SecurityPluginSetup } from '../../../security/public'; @@ -64,6 +65,7 @@ export type APMRequestHandlerContext< config: APMConfig; logger: Logger; plugins: { + observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; }; }; @@ -110,6 +112,7 @@ export interface ServerAPI { config$: Observable; logger: Logger; plugins: { + observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; }; } diff --git a/x-pack/plugins/observability/common/annotations.ts b/x-pack/plugins/observability/common/annotations.ts new file mode 100644 index 0000000000000..6aea4d3d92f9b --- /dev/null +++ b/x-pack/plugins/observability/common/annotations.ts @@ -0,0 +1,51 @@ +/* + * 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 * as t from 'io-ts'; +import { dateAsStringRt } from '../../apm/common/runtime_types/date_as_string_rt'; + +export const createAnnotationRt = t.intersection([ + t.type({ + annotation: t.type({ + type: t.string, + }), + '@timestamp': dateAsStringRt, + message: t.string, + }), + t.partial({ + tags: t.array(t.string), + service: t.partial({ + name: t.string, + environment: t.string, + version: t.string, + }), + }), +]); + +export const deleteAnnotationRt = t.type({ + id: t.string, +}); + +export const getAnnotationByIdRt = t.type({ + id: t.string, +}); + +export interface Annotation { + annotation: { + type: string; + }; + tags?: string[]; + message: string; + service?: { + name?: string; + environment?: string; + version?: string; + }; + event: { + created: string; + }; + '@timestamp': string; +} diff --git a/x-pack/plugins/observability/kibana.json b/x-pack/plugins/observability/kibana.json index 438b9ddea4734..8e2cfe980039c 100644 --- a/x-pack/plugins/observability/kibana.json +++ b/x-pack/plugins/observability/kibana.json @@ -2,6 +2,10 @@ "id": "observability", "version": "8.0.0", "kibanaVersion": "kibana", - "configPath": ["xpack", "observability"], - "ui": true + "configPath": [ + "xpack", + "observability" + ], + "ui": true, + "server": true } diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts new file mode 100644 index 0000000000000..78550b781b411 --- /dev/null +++ b/x-pack/plugins/observability/server/index.ts @@ -0,0 +1,33 @@ +/* + * 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 { schema, TypeOf } from '@kbn/config-schema'; +import { PluginInitializerContext } from 'src/core/server'; +import { ObservabilityPlugin, ObservabilityPluginSetup } from './plugin'; +import { createOrUpdateIndex, MappingsDefinition } from './utils/create_or_update_index'; +import { ScopedAnnotationsClient } from './lib/annotations/bootstrap_annotations'; + +export const config = { + schema: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + annotations: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + index: schema.string({ defaultValue: 'observability-annotations' }), + }), + }), +}; + +export type ObservabilityConfig = TypeOf; + +export const plugin = (initContext: PluginInitializerContext) => + new ObservabilityPlugin(initContext); + +export { + createOrUpdateIndex, + MappingsDefinition, + ObservabilityPluginSetup, + ScopedAnnotationsClient, +}; diff --git a/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts new file mode 100644 index 0000000000000..58639ef084ce6 --- /dev/null +++ b/x-pack/plugins/observability/server/lib/annotations/bootstrap_annotations.ts @@ -0,0 +1,42 @@ +/* + * 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 { CoreSetup, PluginInitializerContext, KibanaRequest } from 'kibana/server'; +import { PromiseReturnType } from '../../../typings/common'; +import { createAnnotationsClient } from './create_annotations_client'; +import { registerAnnotationAPIs } from './register_annotation_apis'; + +interface Params { + index: string; + core: CoreSetup; + context: PluginInitializerContext; +} + +export type ScopedAnnotationsClientFactory = PromiseReturnType< + typeof bootstrapAnnotations +>['getScopedAnnotationsClient']; + +export type ScopedAnnotationsClient = ReturnType; +export type AnnotationsAPI = PromiseReturnType; + +export async function bootstrapAnnotations({ index, core, context }: Params) { + const logger = context.logger.get('annotations'); + + registerAnnotationAPIs({ + core, + index, + logger, + }); + + return { + getScopedAnnotationsClient: (request: KibanaRequest) => { + return createAnnotationsClient({ + index, + apiCaller: core.elasticsearch.dataClient.asScoped(request).callAsCurrentUser, + logger, + }); + }, + }; +} diff --git a/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts new file mode 100644 index 0000000000000..3f2604468e17c --- /dev/null +++ b/x-pack/plugins/observability/server/lib/annotations/create_annotations_client.ts @@ -0,0 +1,106 @@ +/* + * 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 { APICaller, Logger } from 'kibana/server'; +import * as t from 'io-ts'; +import { Client } from 'elasticsearch'; +import { + createAnnotationRt, + deleteAnnotationRt, + Annotation, + getAnnotationByIdRt, +} from '../../../common/annotations'; +import { PromiseReturnType } from '../../../typings/common'; +import { createOrUpdateIndex } from '../../utils/create_or_update_index'; +import { mappings } from './mappings'; + +type CreateParams = t.TypeOf; +type DeleteParams = t.TypeOf; +type GetByIdParams = t.TypeOf; + +interface IndexDocumentResponse { + _shards: { + total: number; + failed: number; + successful: number; + }; + _index: string; + _type: string; + _id: string; + _version: number; + _seq_no: number; + _primary_term: number; + result: string; +} + +export function createAnnotationsClient(params: { + index: string; + apiCaller: APICaller; + logger: Logger; +}) { + const { index, apiCaller, logger } = params; + + const initIndex = () => + createOrUpdateIndex({ + index, + mappings, + apiCaller, + logger, + }); + + return { + get index() { + return index; + }, + create: async ( + createParams: CreateParams + ): Promise<{ _id: string; _index: string; _source: Annotation }> => { + const indexExists = await apiCaller('indices.exists', { + index, + }); + + if (!indexExists) { + await initIndex(); + } + + const annotation = { + ...createParams, + event: { + created: new Date().toISOString(), + }, + }; + + const response = (await apiCaller('index', { + index, + body: annotation, + refresh: 'wait_for', + })) as IndexDocumentResponse; + + return apiCaller('get', { + index, + id: response._id, + }); + }, + getById: async (getByIdParams: GetByIdParams) => { + const { id } = getByIdParams; + + return apiCaller('get', { + id, + index, + }); + }, + delete: async (deleteParams: DeleteParams) => { + const { id } = deleteParams; + + const response = (await apiCaller('delete', { + index, + id, + refresh: 'wait_for', + })) as PromiseReturnType; + return response; + }, + }; +} diff --git a/x-pack/plugins/observability/server/lib/annotations/mappings.ts b/x-pack/plugins/observability/server/lib/annotations/mappings.ts new file mode 100644 index 0000000000000..db85f2d18df1d --- /dev/null +++ b/x-pack/plugins/observability/server/lib/annotations/mappings.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +export const mappings = { + dynamic: 'strict', + properties: { + annotation: { + properties: { + type: { + type: 'keyword', + }, + }, + }, + message: { + type: 'text', + }, + tags: { + type: 'keyword', + }, + '@timestamp': { + type: 'date', + }, + event: { + properties: { + created: { + type: 'date', + }, + }, + }, + service: { + properties: { + name: { + type: 'keyword', + }, + environment: { + type: 'keyword', + }, + version: { + type: 'keyword', + }, + }, + }, + }, +} as const; diff --git a/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts new file mode 100644 index 0000000000000..3c29822acd6dd --- /dev/null +++ b/x-pack/plugins/observability/server/lib/annotations/register_annotation_apis.ts @@ -0,0 +1,109 @@ +/* + * 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 * as t from 'io-ts'; +import { schema } from '@kbn/config-schema'; +import { CoreSetup, RequestHandler, Logger } from 'kibana/server'; +import { PathReporter } from 'io-ts/lib/PathReporter'; +import { isLeft } from 'fp-ts/lib/Either'; +import { + getAnnotationByIdRt, + createAnnotationRt, + deleteAnnotationRt, +} from '../../../common/annotations'; +import { ScopedAnnotationsClient } from './bootstrap_annotations'; +import { createAnnotationsClient } from './create_annotations_client'; + +const unknowns = schema.object({}, { unknowns: 'allow' }); + +export function registerAnnotationAPIs({ + core, + index, + logger, +}: { + core: CoreSetup; + index: string; + logger: Logger; +}) { + function wrapRouteHandler>( + types: TType, + handler: (params: { data: t.TypeOf; client: ScopedAnnotationsClient }) => Promise + ): RequestHandler { + return async (...args: Parameters) => { + const [, request, response] = args; + + const rt = types; + + const data = { + body: request.body, + query: request.query, + params: request.params, + }; + + const validation = rt.decode(data); + + if (isLeft(validation)) { + return response.badRequest({ + body: PathReporter.report(validation).join(', '), + }); + } + + const apiCaller = core.elasticsearch.dataClient.asScoped(request).callAsCurrentUser; + + const client = createAnnotationsClient({ + index, + apiCaller, + logger, + }); + + const res = await handler({ + data: validation.right, + client, + }); + + return response.ok({ + body: res, + }); + }; + } + + const router = core.http.createRouter(); + + router.post( + { + path: '/api/observability/annotation', + validate: { + body: unknowns, + }, + }, + wrapRouteHandler(t.type({ body: createAnnotationRt }), ({ data, client }) => { + return client.create(data.body); + }) + ); + + router.delete( + { + path: '/api/observability/annotation/{id}', + validate: { + params: unknowns, + }, + }, + wrapRouteHandler(t.type({ params: deleteAnnotationRt }), ({ data, client }) => { + return client.delete(data.params); + }) + ); + + router.get( + { + path: '/api/observability/annotation/{id}', + validate: { + params: unknowns, + }, + }, + wrapRouteHandler(t.type({ params: getAnnotationByIdRt }), ({ data, client }) => { + return client.getById(data.params); + }) + ); +} diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts new file mode 100644 index 0000000000000..86cac2f340e44 --- /dev/null +++ b/x-pack/plugins/observability/server/plugin.ts @@ -0,0 +1,59 @@ +/* + * 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 { PluginInitializerContext, Plugin, CoreSetup } from 'src/core/server'; +import { take } from 'rxjs/operators'; +import { ObservabilityConfig } from '.'; +import { + bootstrapAnnotations, + ScopedAnnotationsClient, + ScopedAnnotationsClientFactory, + AnnotationsAPI, +} from './lib/annotations/bootstrap_annotations'; + +type LazyScopedAnnotationsClientFactory = ( + ...args: Parameters +) => Promise; + +export interface ObservabilityPluginSetup { + getScopedAnnotationsClient: LazyScopedAnnotationsClientFactory; +} + +export class ObservabilityPlugin implements Plugin { + constructor(private readonly initContext: PluginInitializerContext) { + this.initContext = initContext; + } + + public async setup(core: CoreSetup, plugins: {}): Promise { + const config$ = this.initContext.config.create(); + + const config = await config$.pipe(take(1)).toPromise(); + + let annotationsApiPromise: Promise | undefined; + + if (config.annotations.enabled) { + annotationsApiPromise = bootstrapAnnotations({ + core, + index: config.annotations.index, + context: this.initContext, + }).catch(err => { + const logger = this.initContext.logger.get('annotations'); + logger.warn(err); + throw err; + }); + } + + return { + getScopedAnnotationsClient: async (...args) => { + const api = await annotationsApiPromise; + return api?.getScopedAnnotationsClient(...args); + }, + }; + } + + public start() {} + + public stop() {} +} diff --git a/x-pack/plugins/observability/server/utils/create_or_update_index.ts b/x-pack/plugins/observability/server/utils/create_or_update_index.ts new file mode 100644 index 0000000000000..2c6f3dbefdeb1 --- /dev/null +++ b/x-pack/plugins/observability/server/utils/create_or_update_index.ts @@ -0,0 +1,108 @@ +/* + * 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 pRetry from 'p-retry'; +import { Logger, APICaller } from 'src/core/server'; + +export interface MappingsObject { + type: string; + ignore_above?: number; + scaling_factor?: number; + ignore_malformed?: boolean; + coerce?: boolean; + fields?: Record; +} + +export interface MappingsDefinition { + dynamic?: boolean | 'strict'; + properties: Record; + dynamic_templates?: any[]; +} + +export async function createOrUpdateIndex({ + index, + mappings, + apiCaller, + logger, +}: { + index: string; + mappings: MappingsDefinition; + apiCaller: APICaller; + logger: Logger; +}) { + try { + /* + * In some cases we could be trying to create an index before ES is ready. + * When this happens, we retry creating the index with exponential backoff. + * We use retry's default formula, meaning that the first retry happens after 2s, + * the 5th after 32s, and the final attempt after around 17m. If the final attempt fails, + * the error is logged to the console. + * See https://github.com/sindresorhus/p-retry and https://github.com/tim-kos/node-retry. + */ + await pRetry( + async () => { + const indexExists = await apiCaller('indices.exists', { index }); + const result = indexExists + ? await updateExistingIndex({ + index, + apiCaller, + mappings, + }) + : await createNewIndex({ + index, + apiCaller, + mappings, + }); + + if (!result.acknowledged) { + const resultError = result && result.error && JSON.stringify(result.error); + throw new Error(resultError); + } + }, + { + onFailedAttempt: e => { + logger.warn(`Could not create index: '${index}'. Retrying...`); + logger.warn(e); + }, + } + ); + } catch (e) { + logger.error(`Could not create index: '${index}'. Error: ${e.message}.`); + } +} + +function createNewIndex({ + index, + apiCaller, + mappings, +}: { + index: string; + apiCaller: APICaller; + mappings: MappingsDefinition; +}) { + return apiCaller('indices.create', { + index, + body: { + // auto_expand_replicas: Allows cluster to not have replicas for this index + settings: { 'index.auto_expand_replicas': '0-1' }, + mappings, + }, + }); +} + +function updateExistingIndex({ + index, + apiCaller, + mappings, +}: { + index: string; + apiCaller: APICaller; + mappings: MappingsDefinition; +}) { + return apiCaller('indices.putMapping', { + index, + body: mappings, + }); +} diff --git a/x-pack/plugins/observability/typings/common.ts b/x-pack/plugins/observability/typings/common.ts new file mode 100644 index 0000000000000..b4a90934a9f49 --- /dev/null +++ b/x-pack/plugins/observability/typings/common.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export type PromiseReturnType = Func extends (...args: any[]) => Promise + ? Value + : Func; diff --git a/x-pack/test/api_integration/apis/apm/annotations.ts b/x-pack/test/api_integration/apis/apm/annotations.ts new file mode 100644 index 0000000000000..4746a7713f34b --- /dev/null +++ b/x-pack/test/api_integration/apis/apm/annotations.ts @@ -0,0 +1,389 @@ +/* + * 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 expect from '@kbn/expect'; +import { merge, cloneDeep, isPlainObject } from 'lodash'; +import { JsonObject } from 'src/plugins/kibana_utils/common'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const DEFAULT_INDEX_NAME = 'observability-annotations'; + +export default function annotationApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + function expectContainsObj(source: JsonObject, expected: JsonObject) { + expect(source).to.eql( + merge(cloneDeep(source), expected, (a, b) => { + if (isPlainObject(a) && isPlainObject(b)) { + return undefined; + } + return b; + }) + ); + } + + function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { + switch (method.toLowerCase()) { + case 'get': + return supertest.get(url).set('kbn-xsrf', 'foo'); + + case 'post': + return supertest + .post(url) + .send(data) + .set('kbn-xsrf', 'foo'); + + default: + throw new Error(`Unsupported methoed ${method}`); + } + } + + describe('APM annotations', () => { + describe('when creating an annotation', () => { + afterEach(async () => { + const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; + if (indexExists) { + await es.indices.delete({ + index: DEFAULT_INDEX_NAME, + }); + } + }); + + it('fails with a 400 bad request if data is missing', async () => { + const response = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + }); + + expect(response.status).to.be(400); + }); + + it('fails with a 400 bad request if data is invalid', async () => { + const invalidTimestampResponse = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': 'foo', + message: 'foo', + }, + }); + + expect(invalidTimestampResponse.status).to.be(400); + + const missingServiceVersionResponse = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': new Date().toISOString(), + message: 'New deployment', + }, + }); + + expect(missingServiceVersionResponse.status).to.be(400); + }); + + it('completes with a 200 and the created annotation if data is complete and valid', async () => { + const timestamp = new Date().toISOString(); + + const response = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': timestamp, + message: 'New deployment', + tags: ['foo'], + service: { + version: '1.1', + environment: 'production', + }, + }, + }); + + expect(response.status).to.be(200); + + expectContainsObj(response.body, { + _source: { + annotation: { + type: 'deployment', + }, + tags: ['apm', 'foo'], + message: 'New deployment', + '@timestamp': timestamp, + service: { + name: 'opbeans-java', + version: '1.1', + environment: 'production', + }, + }, + }); + }); + + it('prefills `message` and `tags`', async () => { + const timestamp = new Date().toISOString(); + + const response = await request({ + url: '/api/apm/services/opbeans-java/annotation', + method: 'POST', + data: { + '@timestamp': timestamp, + service: { + version: '1.1', + }, + }, + }); + + expectContainsObj(response.body, { + _source: { + annotation: { + type: 'deployment', + }, + tags: ['apm'], + message: '1.1', + '@timestamp': timestamp, + service: { + name: 'opbeans-java', + version: '1.1', + }, + }, + }); + }); + }); + + describe('when mixing stored and derived annotations', () => { + const transactionIndexName = 'apm-8.0.0-transaction'; + const serviceName = 'opbeans-java'; + + beforeEach(async () => { + await es.indices.create({ + index: transactionIndexName, + body: { + mappings: { + properties: { + service: { + properties: { + name: { + type: 'keyword', + }, + version: { + type: 'keyword', + }, + environment: { + type: 'keyword', + }, + }, + }, + '@timestamp': { + type: 'date', + }, + observer: { + properties: { + version_major: { + type: 'long', + }, + }, + }, + }, + }, + }, + }); + + await es.index({ + index: transactionIndexName, + body: { + '@timestamp': new Date(2020, 4, 2, 18, 30).toISOString(), + processor: { + event: 'transaction', + }, + service: { + name: serviceName, + version: '1.1', + }, + observer: { + version_major: 8, + }, + }, + refresh: 'wait_for', + }); + + await es.index({ + index: transactionIndexName, + body: { + '@timestamp': new Date(2020, 4, 2, 19, 30).toISOString(), + processor: { + event: 'transaction', + }, + service: { + name: serviceName, + version: '1.2', + environment: 'production', + }, + observer: { + version_major: 8, + }, + }, + refresh: 'wait_for', + }); + }); + + afterEach(async () => { + await es.indices.delete({ + index: transactionIndexName, + }); + + const annotationIndexExists = ( + await es.indices.exists({ + index: DEFAULT_INDEX_NAME, + }) + ).body; + + if (annotationIndexExists) { + await es.indices.delete({ + index: DEFAULT_INDEX_NAME, + }); + } + }); + + it('returns the derived annotations if there are no stored annotations', async () => { + const range = { + start: new Date(2020, 4, 2, 18).toISOString(), + end: new Date(2020, 4, 2, 20).toISOString(), + }; + + const response = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${range.start}&end=${range.end}`, + method: 'GET', + }); + + expect(response.status).to.be(200); + + expect(response.body.annotations.length).to.be(2); + expect(response.body.annotations[0].text).to.be('1.1'); + expect(response.body.annotations[1].text).to.be('1.2'); + }); + + it('returns the stored annotations only if there are any', async () => { + const range = { + start: new Date(2020, 4, 2, 18).toISOString(), + end: new Date(2020, 4, 2, 23).toISOString(), + }; + + expect( + ( + await request({ + url: `/api/apm/services/${serviceName}/annotation`, + method: 'POST', + data: { + service: { + version: '1.3', + }, + '@timestamp': new Date(2020, 4, 2, 21, 30).toISOString(), + }, + }) + ).status + ).to.be(200); + + const response = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${range.start}&end=${range.end}`, + method: 'GET', + }); + + expect(response.body.annotations.length).to.be(1); + expect(response.body.annotations[0].text).to.be('1.3'); + + const earlierRange = { + start: new Date(2020, 4, 2, 18).toISOString(), + end: new Date(2020, 4, 2, 20).toISOString(), + }; + + expect( + ( + await request({ + url: `/api/apm/services/${serviceName}/annotation`, + method: 'POST', + data: { + service: { + version: '1.3', + }, + '@timestamp': new Date(2020, 4, 2, 21, 30).toISOString(), + }, + }) + ).status + ).to.be(200); + + const responseFromEarlierRange = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${earlierRange.start}&end=${earlierRange.end}`, + method: 'GET', + }); + + expect(responseFromEarlierRange.body.annotations.length).to.be(2); + expect(responseFromEarlierRange.body.annotations[0].text).to.be('1.1'); + expect(responseFromEarlierRange.body.annotations[1].text).to.be('1.2'); + }); + + it('returns stored annotations for the given environment', async () => { + expect( + ( + await request({ + url: `/api/apm/services/${serviceName}/annotation`, + method: 'POST', + data: { + service: { + version: '1.3', + }, + '@timestamp': new Date(2020, 4, 2, 21, 30).toISOString(), + }, + }) + ).status + ).to.be(200); + + expect( + ( + await request({ + url: `/api/apm/services/${serviceName}/annotation`, + method: 'POST', + data: { + service: { + version: '1.4', + environment: 'production', + }, + '@timestamp': new Date(2020, 4, 2, 21, 31).toISOString(), + }, + }) + ).status + ).to.be(200); + + const range = { + start: new Date(2020, 4, 2, 18).toISOString(), + end: new Date(2020, 4, 2, 23).toISOString(), + }; + + const allEnvironmentsResponse = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${range.start}&end=${range.end}`, + method: 'GET', + }); + + expect(allEnvironmentsResponse.body.annotations.length).to.be(2); + + const productionEnvironmentResponse = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${range.start}&end=${range.end}&environment=production`, + method: 'GET', + }); + + expect(productionEnvironmentResponse.body.annotations.length).to.be(1); + expect(productionEnvironmentResponse.body.annotations[0].text).to.be('1.4'); + + const missingEnvironmentsResponse = await request({ + url: `/api/apm/services/${serviceName}/annotation/search?start=${range.start}&end=${range.end}&environment=ENVIRONMENT_NOT_DEFINED`, + method: 'GET', + }); + + expect(missingEnvironmentsResponse.body.annotations.length).to.be(1); + expect(missingEnvironmentsResponse.body.annotations[0].text).to.be('1.3'); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/apm/feature_controls.ts b/x-pack/test/api_integration/apis/apm/feature_controls.ts index 9f76941935bb7..5f61c963a69aa 100644 --- a/x-pack/test/api_integration/apis/apm/feature_controls.ts +++ b/x-pack/test/api_integration/apis/apm/feature_controls.ts @@ -42,7 +42,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext) { // this doubles as a smoke test for the _debug query parameter req: { - url: `/api/apm/services/foo/errors?start=${start}&end=${end}&uiFilters=%7B%7D_debug=true`, + url: `/api/apm/services/foo/errors?start=${start}&end=${end}&uiFilters=%7B%7D&_debug=true`, }, expectForbidden: expect404, expectResponse: expect200, diff --git a/x-pack/test/api_integration/apis/apm/index.ts b/x-pack/test/api_integration/apis/apm/index.ts index 4a4265cfd0739..de076e8c46729 100644 --- a/x-pack/test/api_integration/apis/apm/index.ts +++ b/x-pack/test/api_integration/apis/apm/index.ts @@ -8,6 +8,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('APM specs', () => { + loadTestFile(require.resolve('./annotations')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./agent_configuration')); loadTestFile(require.resolve('./custom_link')); diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js index 0a87dcb4b5bb0..75fa90bb4c3fe 100644 --- a/x-pack/test/api_integration/apis/index.js +++ b/x-pack/test/api_integration/apis/index.js @@ -31,5 +31,6 @@ export default function({ loadTestFile }) { loadTestFile(require.resolve('./ingest')); loadTestFile(require.resolve('./endpoint')); loadTestFile(require.resolve('./ml')); + loadTestFile(require.resolve('./observability')); }); } diff --git a/x-pack/test/api_integration/apis/observability/annotations.ts b/x-pack/test/api_integration/apis/observability/annotations.ts new file mode 100644 index 0000000000000..6d32162bfcc65 --- /dev/null +++ b/x-pack/test/api_integration/apis/observability/annotations.ts @@ -0,0 +1,290 @@ +/* + * 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 expect from '@kbn/expect'; +import { JsonObject } from 'src/plugins/kibana_utils/common'; +import { Annotation } from '../../../../plugins/observability/common/annotations'; +import { ESSearchHit } from '../../../../plugins/apm/typings/elasticsearch'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const DEFAULT_INDEX_NAME = 'observability-annotations'; + +export default function annotationApiTests({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const es = getService('es'); + + function request({ method, url, data }: { method: string; url: string; data?: JsonObject }) { + switch (method.toLowerCase()) { + case 'get': + return supertest.get(url).set('kbn-xsrf', 'foo'); + + case 'post': + return supertest + .post(url) + .send(data) + .set('kbn-xsrf', 'foo'); + + case 'delete': + return supertest + .delete(url) + .send(data) + .set('kbn-xsrf', 'foo'); + + default: + throw new Error(`Unsupported methoed ${method}`); + } + } + + describe('Observability annotations', () => { + describe('when creating an annotation', () => { + afterEach(async () => { + const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; + if (indexExists) { + await es.indices.delete({ + index: DEFAULT_INDEX_NAME, + }); + } + }); + + it('fails with a 400 bad request if data is missing', async () => { + const response = await request({ + url: '/api/observability/annotation', + method: 'POST', + }); + + expect(response.status).to.be(400); + }); + + it('fails with a 400 bad request if data is invalid', async () => { + const invalidTimestampResponse = await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': 'foo', + message: 'foo', + }, + }); + + expect(invalidTimestampResponse.status).to.be(400); + + const missingMessageResponse = await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + }, + }); + + expect(missingMessageResponse.status).to.be(400); + }); + + it('completes with a 200 and the created annotation if data is complete and valid', async () => { + const timestamp = new Date().toISOString(); + + const response = await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': timestamp, + message: 'test message', + tags: ['apm'], + }, + }); + + expect(response.status).to.be(200); + + const { _source, _id, _index } = response.body; + + expect(response.body).to.eql({ + _index, + _id, + _primary_term: 1, + _seq_no: 0, + _version: 1, + found: true, + _source: { + annotation: { + type: 'deployment', + }, + '@timestamp': timestamp, + message: 'test message', + tags: ['apm'], + event: { + created: _source.event.created, + }, + }, + }); + + expect(_id).to.be.a('string'); + + expect(_source.event.created).to.be.a('string'); + + const created = new Date(_source.event.created).getTime(); + expect(created).to.be.greaterThan(0); + expect(_index).to.be(DEFAULT_INDEX_NAME); + }); + + it('indexes the annotation', async () => { + const response = await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: 'test message', + tags: ['apm'], + }, + }); + + expect(response.status).to.be(200); + + const search = await es.search({ + index: DEFAULT_INDEX_NAME, + track_total_hits: true, + }); + + expect(search.body.hits.total.value).to.be(1); + + expect(search.body.hits.hits[0]._source).to.eql(response.body._source); + expect(search.body.hits.hits[0]._id).to.eql(response.body._id); + }); + + it('returns the annotation', async () => { + const { _id: id1 } = ( + await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: '1', + tags: ['apm'], + }, + }) + ).body; + + const { _id: id2 } = ( + await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: '2', + tags: ['apm'], + }, + }) + ).body; + + expect( + ( + await request({ + url: `/api/observability/annotation/${id1}`, + method: 'GET', + }) + ).body._source.message + ).to.be('1'); + + expect( + ( + await request({ + url: `/api/observability/annotation/${id2}`, + method: 'GET', + }) + ).body._source.message + ).to.be('2'); + }); + + it('deletes the annotation', async () => { + await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: 'test message', + tags: ['apm'], + }, + }); + + await request({ + url: '/api/observability/annotation', + method: 'POST', + data: { + annotation: { + type: 'deployment', + }, + '@timestamp': new Date().toISOString(), + message: 'test message 2', + tags: ['apm'], + }, + }); + + const initialSearch = await es.search({ + index: DEFAULT_INDEX_NAME, + track_total_hits: true, + }); + + expect(initialSearch.body.hits.total.value).to.be(2); + + const [id1, id2] = initialSearch.body.hits.hits.map( + (hit: ESSearchHit) => hit._id + ); + + expect( + ( + await request({ + url: `/api/observability/annotation/${id1}`, + method: 'DELETE', + }) + ).status + ).to.be(200); + + const searchAfterFirstDelete = await es.search({ + index: DEFAULT_INDEX_NAME, + track_total_hits: true, + }); + + expect(searchAfterFirstDelete.body.hits.total.value).to.be(1); + + expect(searchAfterFirstDelete.body.hits.hits[0]._id).to.be(id2); + + expect( + ( + await request({ + url: `/api/observability/annotation/${id2}`, + method: 'DELETE', + }) + ).status + ).to.be(200); + + const searchAfterSecondDelete = await es.search({ + index: DEFAULT_INDEX_NAME, + track_total_hits: true, + }); + + expect(searchAfterSecondDelete.body.hits.total.value).to.be(0); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/observability/index.ts b/x-pack/test/api_integration/apis/observability/index.ts new file mode 100644 index 0000000000000..25e3e0693c3c0 --- /dev/null +++ b/x-pack/test/api_integration/apis/observability/index.ts @@ -0,0 +1,13 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('Observability specs', () => { + loadTestFile(require.resolve('./annotations')); + }); +} From 52a232f40b61dbe24c722c4154e9702ee5bef486 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 5 May 2020 19:55:33 +0200 Subject: [PATCH 17/72] load react component lazily to reduce entry bundle (#65267) * load react component lazily to reduce entry bundle * address comments --- .../telemetry_management_section.test.tsx.snap | 2 +- .../telemetry_management_section.test.tsx | 9 +++++---- .../telemetry_management_section.tsx | 4 ++++ .../telemetry_management_section_wrapper.tsx | 18 +++++++++++------- .../public/{plugin.ts => plugin.tsx} | 0 5 files changed, 21 insertions(+), 12 deletions(-) rename src/plugins/telemetry_management_section/public/{plugin.ts => plugin.tsx} (100%) diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index 8c0117e5a7266..c392d8ce64205 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -489,4 +489,4 @@ exports[`TelemetryManagementSectionComponent renders null because query does not /> `; -exports[`TelemetryManagementSectionComponent test the wrapper (for coverage purposes) 1`] = `""`; +exports[`TelemetryManagementSectionComponent test the wrapper (for coverage purposes) 1`] = `null`; diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx index d0c2bd13f802d..c13f639f31447 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx @@ -18,10 +18,9 @@ */ import React from 'react'; import { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { TelemetryManagementSection } from './telemetry_management_section'; +import TelemetryManagementSection from './telemetry_management_section'; import { TelemetryService } from '../../../telemetry/public/services'; import { coreMock } from '../../../../core/public/mocks'; -import { telemetryManagementSectionWrapper } from './telemetry_management_section_wrapper'; describe('TelemetryManagementSectionComponent', () => { const coreStart = coreMock.createStart(); @@ -270,10 +269,12 @@ describe('TelemetryManagementSectionComponent', () => { notifications: coreStart.notifications, http: coreSetup.http, }); - const Wrapper = telemetryManagementSectionWrapper(telemetryService); + expect( shallowWithIntl( - { }); }; } + +// required for lazy loading +// eslint-disable-next-line import/no-default-export +export default TelemetryManagementSection; diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx index b8b20b68f666e..f61268c4772a3 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section_wrapper.tsx @@ -17,23 +17,27 @@ * under the License. */ -import React from 'react'; +import React, { lazy, Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; import { TelemetryPluginSetup } from 'src/plugins/telemetry/public'; -import { TelemetryManagementSection } from './telemetry_management_section'; // It should be this but the types are way too vague in the AdvancedSettings plugin `Record` // type Props = Omit; type Props = any; +const TelemetryManagementSectionComponent = lazy(() => import('./telemetry_management_section')); + export function telemetryManagementSectionWrapper( telemetryService: TelemetryPluginSetup['telemetryService'] ) { const TelemetryManagementSectionWrapper = (props: Props) => ( - + }> + + ); return TelemetryManagementSectionWrapper; diff --git a/src/plugins/telemetry_management_section/public/plugin.ts b/src/plugins/telemetry_management_section/public/plugin.tsx similarity index 100% rename from src/plugins/telemetry_management_section/public/plugin.ts rename to src/plugins/telemetry_management_section/public/plugin.tsx From 283b61b1d8a64d7c6fcf8a380f28643aa6d462a0 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Tue, 5 May 2020 13:59:55 -0400 Subject: [PATCH 18/72] Increase verify es job timeout to 2.5 hours (#65313) --- .ci/es-snapshots/Jenkinsfile_verify_es | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/es-snapshots/Jenkinsfile_verify_es b/.ci/es-snapshots/Jenkinsfile_verify_es index 75b686abe845f..c87ca01354315 100644 --- a/.ci/es-snapshots/Jenkinsfile_verify_es +++ b/.ci/es-snapshots/Jenkinsfile_verify_es @@ -19,7 +19,7 @@ currentBuild.description = "ES: ${SNAPSHOT_VERSION}
Kibana: ${params.branch def SNAPSHOT_MANIFEST = "https://storage.googleapis.com/kibana-ci-es-snapshots-daily/${SNAPSHOT_VERSION}/archives/${SNAPSHOT_ID}/manifest.json" -kibanaPipeline(timeoutMinutes: 120) { +kibanaPipeline(timeoutMinutes: 150) { catchErrors { slackNotifications.onFailure( title: ":broken_heart: *<${env.BUILD_URL}|[${SNAPSHOT_VERSION}] ES Snapshot Verification Failure>*", From 7d5aa80976cf8d55d570a042877b5479eae799dc Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 5 May 2020 11:34:19 -0700 Subject: [PATCH 19/72] [Metrics UI] Migrating Docker network fields (#65133) --- .../container/metrics/snapshot/rx.ts | 2 +- .../container/metrics/snapshot/tx.ts | 2 +- .../metrics/tsvb/container_network_traffic.ts | 56 +++++++++++++++---- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts b/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts index 6843f6149c711..76d61e3b94441 100644 --- a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts +++ b/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts @@ -7,6 +7,6 @@ import { networkTrafficWithInterfaces } from '../../../shared/metrics/snapshot/network_traffic_with_interfaces'; export const rx = networkTrafficWithInterfaces( 'rx', - 'docker.network.in.bytes', + 'docker.network.inbound.bytes', 'docker.network.interface' ); diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts b/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts index bccb4e60e9d19..4f413ed350f40 100644 --- a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts +++ b/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts @@ -7,6 +7,6 @@ import { networkTrafficWithInterfaces } from '../../../shared/metrics/snapshot/network_traffic_with_interfaces'; export const tx = networkTrafficWithInterfaces( 'tx', - 'docker.network.out.bytes', + 'docker.network.outbound.bytes', 'docker.network.interface' ); diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts b/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts index 18daac446bdcd..0300b9deee115 100644 --- a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts +++ b/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts @@ -20,37 +20,73 @@ export const containerNetworkTraffic: TSVBMetricModelCreator = ( series: [ { id: 'tx', - split_mode: 'everything', metrics: [ { - field: 'docker.network.out.bytes', - id: 'avg-network-out', - type: 'avg', + field: 'docker.network.outbound.bytes', + id: 'max-net-out', + type: 'max', + }, + { + field: 'max-net-out', + id: 'deriv-max-net-out', + type: 'derivative', + unit: '1s', + }, + { + id: 'posonly-deriv-max-net-out', + type: 'calculation', + variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-out' }], + script: 'params.rate > 0.0 ? params.rate : 0.0', + }, + { + function: 'sum', + id: 'seriesagg-sum', + type: 'series_agg', }, ], + split_mode: 'terms', + terms_field: 'docker.network.interface', }, { id: 'rx', - split_mode: 'everything', metrics: [ { - field: 'docker.network.in.bytes', - id: 'avg-network-in', - type: 'avg', + field: 'docker.network.inbound.bytes', + id: 'max-net-in', + type: 'max', }, { - id: 'invert-posonly-deriv-max-network-in', + field: 'max-net-in', + id: 'deriv-max-net-in', + type: 'derivative', + unit: '1s', + }, + { + id: 'posonly-deriv-max-net-in', + type: 'calculation', + variables: [{ id: 'var-rate', name: 'rate', field: 'deriv-max-net-in' }], + script: 'params.rate > 0.0 ? params.rate : 0.0', + }, + { + id: 'calc-invert-rate', script: 'params.rate * -1', type: 'calculation', variables: [ { - field: 'avg-network-in', + field: 'posonly-deriv-max-net-in', id: 'var-rate', name: 'rate', }, ], }, + { + function: 'sum', + id: 'seriesagg-sum', + type: 'series_agg', + }, ], + split_mode: 'terms', + terms_field: 'docker.network.interface', }, ], }); From c2422c9fce05886e268460eab3b34cc1ea7cf9cd Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 5 May 2020 20:37:25 +0200 Subject: [PATCH 20/72] [Uptime] Remove legacy uptime from path labeler (#65054) --- .github/paths-labeller.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index efdb041e2b37a..d9d99fc1416e4 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -8,9 +8,8 @@ - "Feature:ExpressionLanguage": - "src/plugins/expressions/**/*.*" - "src/plugins/bfetch/**/*.*" - - "Team:apm" + - "Team:apm": - "x-pack/plugins/apm/**/*.*" - "x-pack/plugins/apm/**/*.*" - "Team:uptime": - "x-pack/plugins/uptime/**/*.*" - - "x-pack/legacy/plugins/uptime/**/*.*" From 415d33b756d7ad280c3ae054c9caa734bbbe27f3 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 5 May 2020 11:38:20 -0700 Subject: [PATCH 21/72] [ML] Edits create anomaly job intro text (#64607) * Edits create anomaly job intro text * [DOCS] More edits * [DOCS] Removes obsolete translations * [DOCS] Addresses feedback * [DOCS] Update create job breadcrumb Co-authored-by: Elastic Machine --- .../job_creator/multi_metric_job_creator.ts | 2 +- .../common/job_creator/util/general.ts | 2 +- .../single_metric_view/settings.tsx | 2 +- .../jobs/new_job/pages/job_type/page.tsx | 22 +++++-------------- .../public/application/routing/breadcrumbs.ts | 2 +- .../routing/routes/new_job/wizard.tsx | 2 +- .../modules/apache_ecs/manifest.json | 2 +- .../modules/apm_transaction/manifest.json | 2 +- .../manifest.json | 2 +- .../auditbeat_process_hosts_ecs/manifest.json | 2 +- .../modules/logs_ui_analysis/manifest.json | 2 +- .../modules/logs_ui_categories/manifest.json | 2 +- .../metricbeat_system_ecs/manifest.json | 2 +- .../modules/nginx_ecs/manifest.json | 2 +- .../sample_data_ecommerce/manifest.json | 2 +- .../modules/sample_data_weblogs/manifest.json | 2 +- .../modules/siem_auditbeat/manifest.json | 2 +- .../modules/siem_auditbeat_auth/manifest.json | 2 +- .../modules/siem_packetbeat/manifest.json | 2 +- .../modules/siem_winlogbeat/manifest.json | 2 +- .../siem_winlogbeat_auth/manifest.json | 2 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 23 files changed, 26 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts index 6c2030daec39d..10d306c37d114 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/multi_metric_job_creator.ts @@ -19,7 +19,7 @@ import { getRichDetectors } from './util/general'; import { IndexPattern } from '../../../../../../../../../src/plugins/data/public'; export class MultiMetricJobCreator extends JobCreator { - // a multi metric job has one optional overall partition field + // a multi-metric job has one optional overall partition field // which is the same for all detectors. private _splitField: SplitField = null; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts index c487341ab0c36..6d061c2df9ad9 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/util/general.ts @@ -298,7 +298,7 @@ export function getJobCreatorTitle(jobCreator: JobCreatorType) { }); case JOB_TYPE.MULTI_METRIC: return i18n.translate('xpack.ml.newJob.wizard.jobCreatorTitle.multiMetric', { - defaultMessage: 'Multi metric', + defaultMessage: 'Multi-metric', }); case JOB_TYPE.POPULATION: return i18n.translate('xpack.ml.newJob.wizard.jobCreatorTitle.population', { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/single_metric_view/settings.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/single_metric_view/settings.tsx index f8e7275cf15bb..3bcac1cf6876c 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/single_metric_view/settings.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/single_metric_view/settings.tsx @@ -40,7 +40,7 @@ export const SingleMetricSettings: FC = ({ setIsValid }) => {
diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx index 562ef780bd17b..3bfe0569e75be 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx @@ -106,15 +106,15 @@ export const Page: FC = () => { icon: { type: 'createMultiMetricJob', ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricAriaLabel', { - defaultMessage: 'Multi metric job', + defaultMessage: 'Multi-metric job', }), }, title: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricTitle', { - defaultMessage: 'Multi metric', + defaultMessage: 'Multi-metric', }), description: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricDescription', { defaultMessage: - 'Detect anomalies in multiple metrics by splitting a time series by a categorical field.', + 'Detect anomalies with one or more metrics and optionally split the analysis.', }), id: 'mlJobTypeLinkMultiMetricJob', }, @@ -208,7 +208,7 @@ export const Page: FC = () => {

@@ -217,8 +217,8 @@ export const Page: FC = () => {

@@ -244,16 +244,6 @@ export const Page: FC = () => { />

- - -

- -

-
- diff --git a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts index 588f4423c3190..288914f702728 100644 --- a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts +++ b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts @@ -37,7 +37,7 @@ export const DATA_VISUALIZER_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ export const CREATE_JOB_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ text: i18n.translate('xpack.ml.createJobsBreadcrumbLabel', { - defaultMessage: 'Create jobs', + defaultMessage: 'Create job', }), href: '#/jobs/new_job', }); diff --git a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx index 619a27013b6dd..14df9a1d44a85 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx @@ -42,7 +42,7 @@ const multiMetricBreadcrumbs = [ ...baseBreadcrumbs, { text: i18n.translate('xpack.ml.jobsBreadcrumbs.multiMetricLabel', { - defaultMessage: 'Multi metric', + defaultMessage: 'Multi-metric', }), href: '', }, diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json index 031cf05ca39cd..c4b6b18f56bc8 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apache_ecs/manifest.json @@ -1,7 +1,7 @@ { "id": "apache_ecs", "title": "Apache access logs", - "description": "Find unusual activity in HTTP access logs from filebeat (ECS)", + "description": "Find unusual activity in HTTP access logs from filebeat (ECS).", "type": "Web Access Logs", "logoFile": "logo.json", "defaultIndexPattern": "filebeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json index 5eac6d090d1b9..5e185e80a6038 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json @@ -1,7 +1,7 @@ { "id": "apm_transaction", "title": "APM", - "description": "Detect anomalies in high mean of transaction duration (ECS)", + "description": "Detect anomalies in high mean of transaction duration (ECS).", "type": "Transaction data", "logoFile": "logo.json", "defaultIndexPattern": "apm-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json index 345f061db9de1..7f407c4f5f713 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_docker_ecs/manifest.json @@ -1,7 +1,7 @@ { "id": "auditbeat_process_docker_ecs", "title": "Auditbeat docker processes", - "description": "Detect unusual processes in docker containers from auditd data (ECS)", + "description": "Detect unusual processes in docker containers from auditd data (ECS).", "type": "Auditbeat data", "logoFile": "logo.json", "defaultIndexPattern": "auditbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json index 94254189be172..3f883e0198817 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/auditbeat_process_hosts_ecs/manifest.json @@ -1,7 +1,7 @@ { "id": "auditbeat_process_hosts_ecs", "title": "Auditbeat host processes", - "description": "Detect unusual processes on hosts from auditd data (ECS)", + "description": "Detect unusual processes on hosts from auditd data (ECS).", "type": "Auditbeat data", "logoFile": "logo.json", "defaultIndexPattern": "auditbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json index 28fd590e68363..4c97acedcedcf 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_analysis/manifest.json @@ -1,7 +1,7 @@ { "id": "logs_ui_analysis", "title": "Log Analysis", - "description": "Detect anomalies in log entries via the Logs UI", + "description": "Detect anomalies in log entries via the Logs UI.", "type": "Logs", "logoFile": "logo.json", "jobs": [ diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json index b31ddacde8b6d..d3faa27c29df7 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/logs_ui_categories/manifest.json @@ -1,7 +1,7 @@ { "id": "logs_ui_categories", "title": "Log entry categories", - "description": "Detect anomalies in count of log entries by category", + "description": "Detect anomalies in count of log entries by category.", "type": "Logs", "logoFile": "logo.json", "jobs": [ diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json index 79a201a797008..499896ced7deb 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/metricbeat_system_ecs/manifest.json @@ -2,7 +2,7 @@ "id": "metricbeat_system_ecs", "title": "Metricbeat System", "description": "Detect anomalies in Metricbeat System data (ECS)", - "type": "Metricbeat data", + "type": "Metricbeat data.", "logoFile": "logo.json", "defaultIndexPattern": "metricbeat-*", "query": { diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json index bd31fcd23f504..c39e4e5e4faf6 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/nginx_ecs/manifest.json @@ -1,7 +1,7 @@ { "id": "nginx_ecs", "title": "Nginx access logs", - "description": "Find unusual activity in HTTP access logs from filebeat (ECS)", + "description": "Find unusual activity in HTTP access logs from filebeat (ECS).", "type": "Web Access Logs", "logoFile": "logo.json", "defaultIndexPattern": "filebeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json index dea2875b15160..4c0186023b458 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_ecommerce/manifest.json @@ -1,7 +1,7 @@ { "id": "sample_data_ecommerce", "title": "Kibana sample data eCommerce", - "description": "Find anomalies in eCommerce total sales data", + "description": "Find anomalies in eCommerce total sales data.", "type": "Sample Dataset", "logoFile": "logo.json", "defaultIndexPattern": "kibana_sample_data_ecommerce", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json index 9c3aceba33f38..a0b47e7135312 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/sample_data_weblogs/manifest.json @@ -1,7 +1,7 @@ { "id": "sample_data_weblogs", "title": "Kibana sample data web logs", - "description": "Find anomalies in Kibana sample web logs data", + "description": "Find anomalies in Kibana sample web logs data.", "type": "Sample Dataset", "logoFile": "logo.json", "defaultIndexPattern": "kibana_sample_data_logs", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json index 6238f07413323..3c7b1c7cfffd4 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat/manifest.json @@ -1,7 +1,7 @@ { "id": "siem_auditbeat", "title": "SIEM Auditbeat", - "description": "Detect suspicious network activity and unusual processes in Auditbeat data (beta)", + "description": "Detect suspicious network activity and unusual processes in Auditbeat data (beta).", "type": "Auditbeat data", "logoFile": "logo.json", "defaultIndexPattern": "auditbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json index 4665b695bbf84..4b86752e45a92 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_auditbeat_auth/manifest.json @@ -1,7 +1,7 @@ { "id": "siem_auditbeat_auth", "title": "SIEM Auditbeat Authentication", - "description": "Detect suspicious authentication events in Auditbeat data (beta)", + "description": "Detect suspicious authentication events in Auditbeat data (beta).", "type": "Auditbeat data", "logoFile": "logo.json", "defaultIndexPattern": "auditbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json index 455a6658ac23f..9109cbc15ca6f 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/manifest.json @@ -1,7 +1,7 @@ { "id": "siem_packetbeat", "title": "SIEM Packetbeat", - "description": "Detect suspicious network activity in Packetbeat data (beta)", + "description": "Detect suspicious network activity in Packetbeat data (beta).", "type": "Packetbeat data", "logoFile": "logo.json", "defaultIndexPattern": "packetbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json index 501a900d5badd..682b9a833f23f 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat/manifest.json @@ -1,7 +1,7 @@ { "id": "siem_winlogbeat", "title": "SIEM Winlogbeat", - "description": "Detect unusual processes and network activity in Winlogbeat data (beta)", + "description": "Detect unusual processes and network activity in Winlogbeat data (beta).", "type": "Winlogbeat data", "logoFile": "logo.json", "defaultIndexPattern": "winlogbeat-*", diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json index 89feaf73051b3..b5e65e9638eb2 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_winlogbeat_auth/manifest.json @@ -1,7 +1,7 @@ { "id": "siem_winlogbeat_auth", "title": "SIEM Winlogbeat Authentication", - "description": "Detect suspicious authentication events in Winlogbeat data (beta)", + "description": "Detect suspicious authentication events in Winlogbeat data (beta).", "type": "Winlogbeat data", "logoFile": "logo.json", "defaultIndexPattern": "winlogbeat-*", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 710642b03e329..85b4c7f7eb032 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10252,7 +10252,6 @@ "xpack.ml.newJob.wizard.jobType.singleMetricTitle": "シングルメトリック", "xpack.ml.newJob.wizard.jobType.useSuppliedConfigurationDescription": "データのフィールドが既知のカテゴリーと一致することが認識されました。選択して一連の機械学習ジョブと関連ダッシュボードを作成します。", "xpack.ml.newJob.wizard.jobType.useSuppliedConfigurationTitle": "提供された構成を使用", - "xpack.ml.newJob.wizard.jobType.useWizardDescription": "ウィザードの 1 つを使用し、データの異常を検知する機械学習ジョブを作成します。", "xpack.ml.newJob.wizard.jobType.useWizardTitle": "ウィザードを使用", "xpack.ml.newJob.wizard.jsonFlyout.closeButton": "閉じる", "xpack.ml.newJob.wizard.jsonFlyout.datafeed.title": "データフィード構成 JSON", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cf52ee6f3b515..2f2b2b7f37481 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10258,7 +10258,6 @@ "xpack.ml.newJob.wizard.jobType.singleMetricTitle": "单一指标", "xpack.ml.newJob.wizard.jobType.useSuppliedConfigurationDescription": "数据中的字段已被识别为匹配已知配置。选择并创建一组 Machine Learning 作业和关联的仪表板。", "xpack.ml.newJob.wizard.jobType.useSuppliedConfigurationTitle": "使用提供的配置", - "xpack.ml.newJob.wizard.jobType.useWizardDescription": "使用其中一个向导创建 Machine Learning 作业,以查找数据中的异常。", "xpack.ml.newJob.wizard.jobType.useWizardTitle": "使用向导", "xpack.ml.newJob.wizard.jsonFlyout.closeButton": "关闭", "xpack.ml.newJob.wizard.jsonFlyout.datafeed.title": "数据馈送配置 JSON", From 891e27eb1f654889ad02703003e7b6e0ff3116e1 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 5 May 2020 12:38:52 -0600 Subject: [PATCH 22/72] [Maps] observability real user monitoring solution layer (#64949) * [Maps] observability real user monitoring solution layer * make stateful component * rename RUM to observability * layer select * metrics select * display select * clean up * create cholopleth map layer descriptor * get styling working * fix unique count agg * create geo grid source * render as heatmap * clusters * tslint errors * last tslint fix * only show card when APM index exists * layer label * clean up * fix getLayerWizards * add parans * review feedback * add cluster labels * use green to red ramp * tslint fix Co-authored-by: Elastic Machine --- x-pack/plugins/maps/common/constants.ts | 1 + .../descriptor_types/descriptor_types.d.ts | 1 + .../{get_join_key.ts => get_agg_key.ts} | 15 +- .../maps/common/migrations/join_agg_key.ts | 2 +- .../public/connected_components/_index.scss | 2 +- .../_source_select.scss => _index.scss} | 0 .../layer_addpanel/layer_wizard_select.tsx | 67 ++++ .../layer_addpanel/source_select/_index.scss | 1 - .../source_select/source_select.js | 41 --- .../layer_addpanel/view.js | 8 +- .../public/layers/layer_wizard_registry.ts | 22 +- .../maps/public/layers/load_layer_wizards.ts | 6 +- .../create_layer_descriptor.test.ts | 336 ++++++++++++++++++ .../observability/create_layer_descriptor.ts | 270 ++++++++++++++ .../observability/display_select.tsx | 70 ++++ .../solution_layers/observability/index.ts | 7 + .../observability/layer_select.tsx | 54 +++ .../observability/metric_select.tsx | 89 +++++ .../observability_layer_template.tsx | 82 +++++ .../observability_layer_wizard.tsx | 33 ++ .../sources/es_agg_source/es_agg_source.js | 14 +- .../es_geo_grid_source/es_geo_grid_source.js | 9 +- .../sources/es_search_source/scaling_form.tsx | 10 +- .../sources/es_term_source/es_term_source.js | 11 +- .../kibana_base_map_layer_wizard.tsx | 2 +- .../maps/public/layers/vector_layer.d.ts | 3 +- 26 files changed, 1075 insertions(+), 81 deletions(-) rename x-pack/plugins/maps/common/{get_join_key.ts => get_agg_key.ts} (62%) rename x-pack/plugins/maps/public/connected_components/layer_addpanel/{source_select/_source_select.scss => _index.scss} (100%) create mode 100644 x-pack/plugins/maps/public/connected_components/layer_addpanel/layer_wizard_select.tsx delete mode 100644 x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_index.scss delete mode 100644 x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.test.ts create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.ts create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/display_select.tsx create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/index.ts create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/layer_select.tsx create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/metric_select.tsx create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_template.tsx create mode 100644 x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_wizard.tsx diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index e95fe9500746c..139f9e88094e0 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -57,6 +57,7 @@ export enum SOURCE_TYPES { ES_GEO_GRID = 'ES_GEO_GRID', ES_SEARCH = 'ES_SEARCH', ES_PEW_PEW = 'ES_PEW_PEW', + ES_TERM_SOURCE = 'ES_TERM_SOURCE', EMS_XYZ = 'EMS_XYZ', // identifies a custom TMS source. Name is a little unfortunate. WMS = 'WMS', KIBANA_TILEMAP = 'KIBANA_TILEMAP', diff --git a/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts index 6980f14d0788a..a9a9fa17c41fc 100644 --- a/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts +++ b/x-pack/plugins/maps/common/descriptor_types/descriptor_types.d.ts @@ -71,6 +71,7 @@ export type ESPewPewSourceDescriptor = AbstractESAggSourceDescriptor & { export type ESTermSourceDescriptor = AbstractESAggSourceDescriptor & { indexPatternTitle: string; term: string; // term field name + whereQuery?: Query; }; export type KibanaRegionmapSourceDescriptor = AbstractSourceDescriptor & { diff --git a/x-pack/plugins/maps/common/get_join_key.ts b/x-pack/plugins/maps/common/get_agg_key.ts similarity index 62% rename from x-pack/plugins/maps/common/get_join_key.ts rename to x-pack/plugins/maps/common/get_agg_key.ts index f1ee95126b9a9..19c39b4dfa6bd 100644 --- a/x-pack/plugins/maps/common/get_join_key.ts +++ b/x-pack/plugins/maps/common/get_agg_key.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { AGG_DELIMITER, AGG_TYPE, JOIN_FIELD_NAME_PREFIX } from './constants'; +import { AGG_DELIMITER, AGG_TYPE, COUNT_PROP_NAME, JOIN_FIELD_NAME_PREFIX } from './constants'; -// function in common since its needed by migration export function getJoinAggKey({ aggType, aggFieldName, @@ -15,8 +14,18 @@ export function getJoinAggKey({ aggType: AGG_TYPE; aggFieldName?: string; rightSourceId: string; -}) { +}): string { const metricKey = aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${aggFieldName}` : aggType; return `${JOIN_FIELD_NAME_PREFIX}${metricKey}__${rightSourceId}`; } + +export function getSourceAggKey({ + aggType, + aggFieldName, +}: { + aggType: AGG_TYPE; + aggFieldName?: string; +}): string { + return aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${aggFieldName}` : COUNT_PROP_NAME; +} diff --git a/x-pack/plugins/maps/common/migrations/join_agg_key.ts b/x-pack/plugins/maps/common/migrations/join_agg_key.ts index 97b9ee4692c25..92e3172f218b9 100644 --- a/x-pack/plugins/maps/common/migrations/join_agg_key.ts +++ b/x-pack/plugins/maps/common/migrations/join_agg_key.ts @@ -13,7 +13,7 @@ import { LAYER_TYPE, VECTOR_STYLES, } from '../constants'; -import { getJoinAggKey } from '../get_join_key'; +import { getJoinAggKey } from '../get_agg_key'; import { AggDescriptor, JoinDescriptor, diff --git a/x-pack/plugins/maps/public/connected_components/_index.scss b/x-pack/plugins/maps/public/connected_components/_index.scss index 83042ae1d586c..a961e652046a6 100644 --- a/x-pack/plugins/maps/public/connected_components/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/_index.scss @@ -1,5 +1,5 @@ @import 'gis_map/gis_map'; -@import 'layer_addpanel/source_select/index'; +@import 'layer_addpanel/index'; @import 'layer_panel/index'; @import 'widget_overlay/index'; @import 'toolbar_overlay/index'; diff --git a/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_source_select.scss b/x-pack/plugins/maps/public/connected_components/layer_addpanel/_index.scss similarity index 100% rename from x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_source_select.scss rename to x-pack/plugins/maps/public/connected_components/layer_addpanel/_index.scss diff --git a/x-pack/plugins/maps/public/connected_components/layer_addpanel/layer_wizard_select.tsx b/x-pack/plugins/maps/public/connected_components/layer_addpanel/layer_wizard_select.tsx new file mode 100644 index 0000000000000..0359ed2c6269d --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/layer_addpanel/layer_wizard_select.tsx @@ -0,0 +1,67 @@ +/* + * 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 React, { Component, Fragment } from 'react'; +import { EuiSpacer, EuiCard, EuiIcon } from '@elastic/eui'; +import { getLayerWizards, LayerWizard } from '../../layers/layer_wizard_registry'; + +interface Props { + onSelect: (layerWizard: LayerWizard) => void; +} + +interface State { + layerWizards: LayerWizard[]; +} + +export class LayerWizardSelect extends Component { + private _isMounted: boolean = false; + + state = { + layerWizards: [], + }; + + componentDidMount() { + this._isMounted = true; + this._loadLayerWizards(); + } + + componentWillUnmount() { + this._isMounted = false; + } + + async _loadLayerWizards() { + const layerWizards = await getLayerWizards(); + if (this._isMounted) { + this.setState({ layerWizards }); + } + } + + render() { + return this.state.layerWizards.map((layerWizard: LayerWizard) => { + const icon = layerWizard.icon ? : undefined; + + const onClick = () => { + this.props.onSelect(layerWizard); + }; + + return ( + + + + + ); + }); + } +} diff --git a/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_index.scss b/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_index.scss deleted file mode 100644 index 8ae6970315e13..0000000000000 --- a/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'source_select'; diff --git a/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js b/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js deleted file mode 100644 index 82df9237e6ed3..0000000000000 --- a/x-pack/plugins/maps/public/connected_components/layer_addpanel/source_select/source_select.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { Fragment } from 'react'; - -import { getLayerWizards } from '../../../layers/layer_wizard_registry'; -import { EuiSpacer, EuiCard, EuiIcon } from '@elastic/eui'; -import _ from 'lodash'; - -export function SourceSelect({ updateSourceSelection }) { - const sourceCards = getLayerWizards().map(layerWizard => { - const icon = layerWizard.icon ? : null; - - const onClick = () => { - updateSourceSelection({ - layerWizard: layerWizard, - isIndexingSource: !!layerWizard.isIndexingSource, - }); - }; - - return ( - - - - - ); - }); - - return {sourceCards}; -} diff --git a/x-pack/plugins/maps/public/connected_components/layer_addpanel/view.js b/x-pack/plugins/maps/public/connected_components/layer_addpanel/view.js index 127b99d730db5..730e58a107aad 100644 --- a/x-pack/plugins/maps/public/connected_components/layer_addpanel/view.js +++ b/x-pack/plugins/maps/public/connected_components/layer_addpanel/view.js @@ -5,7 +5,7 @@ */ import React, { Component, Fragment } from 'react'; -import { SourceSelect } from './source_select/source_select'; +import { LayerWizardSelect } from './layer_wizard_select'; import { FlyoutFooter } from './flyout_footer'; import { ImportEditor } from './import_editor'; import { EuiButtonEmpty, EuiPanel, EuiTitle, EuiFlyoutHeader, EuiSpacer } from '@elastic/eui'; @@ -80,8 +80,8 @@ export class AddLayerPanel extends Component { this.props.removeTransientLayer(); }; - _onSourceSelectionChange = ({ layerWizard, isIndexingSource }) => { - this.setState({ layerWizard, importView: isIndexingSource }); + _onWizardSelect = layerWizard => { + this.setState({ layerWizard, importView: !!layerWizard.isIndexingSource }); }; _layerAddHandler = () => { @@ -100,7 +100,7 @@ export class AddLayerPanel extends Component { _renderPanelBody() { if (!this.state.layerWizard) { - return ; + return ; } const backButton = this.props.isIndexingTriggered ? null : ( diff --git a/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts b/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts index 7715541b1c52d..f866fc10b1f47 100644 --- a/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts +++ b/x-pack/plugins/maps/public/layers/layer_wizard_registry.ts @@ -20,7 +20,7 @@ export type RenderWizardArguments = { }; export type LayerWizard = { - checkVisibility?: () => boolean; + checkVisibility?: () => Promise; description: string; icon: string; isIndexingSource?: boolean; @@ -31,11 +31,23 @@ export type LayerWizard = { const registry: LayerWizard[] = []; export function registerLayerWizard(layerWizard: LayerWizard) { - registry.push(layerWizard); + registry.push({ + checkVisibility: async () => { + return true; + }, + ...layerWizard, + }); } -export function getLayerWizards(): LayerWizard[] { - return registry.filter(layerWizard => { - return layerWizard.checkVisibility ? layerWizard.checkVisibility() : true; +export async function getLayerWizards(): Promise { + const promises = registry.map(async layerWizard => { + return { + ...layerWizard, + // @ts-ignore + isVisible: await layerWizard.checkVisibility(), + }; + }); + return (await Promise.all(promises)).filter(({ isVisible }) => { + return isVisible; }); } diff --git a/x-pack/plugins/maps/public/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/layers/load_layer_wizards.ts index 0b83f3bbdc613..098ff51791d79 100644 --- a/x-pack/plugins/maps/public/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/layers/load_layer_wizards.ts @@ -25,17 +25,19 @@ import { tmsLayerWizardConfig } from './sources/xyz_tms_source'; // @ts-ignore import { wmsLayerWizardConfig } from './sources/wms_source'; import { mvtVectorSourceWizardConfig } from './sources/mvt_single_layer_vector_source'; -// @ts-ignore +import { ObservabilityLayerWizardConfig } from './solution_layers/observability'; import { getInjectedVarFunc } from '../kibana_services'; -// Registration order determines display order let registered = false; export function registerLayerWizards() { if (registered) { return; } + + // Registration order determines display order // @ts-ignore registerLayerWizard(uploadLayerWizardConfig); + registerLayerWizard(ObservabilityLayerWizardConfig); // @ts-ignore registerLayerWizard(esDocumentsLayerWizardConfig); // @ts-ignore diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.test.ts b/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.test.ts new file mode 100644 index 0000000000000..6c0b6cdc39b85 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.test.ts @@ -0,0 +1,336 @@ +/* + * 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. + */ + +jest.mock('../../../kibana_services', () => { + const mockUiSettings = { + get: () => { + return undefined; + }, + }; + return { + getUiSettings: () => { + return mockUiSettings; + }, + }; +}); + +jest.mock('uuid/v4', () => { + return function() { + return '12345'; + }; +}); + +import { createLayerDescriptor } from './create_layer_descriptor'; +import { OBSERVABILITY_LAYER_TYPE } from './layer_select'; +import { OBSERVABILITY_METRIC_TYPE } from './metric_select'; +import { DISPLAY } from './display_select'; + +describe('createLayerDescriptor', () => { + test('Should create vector layer descriptor with join when displayed as choropleth', () => { + const layerDescriptor = createLayerDescriptor({ + layer: OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE, + metric: OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION, + display: DISPLAY.CHOROPLETH, + }); + + expect(layerDescriptor).toEqual({ + __dataRequests: [], + alpha: 0.75, + id: '12345', + joins: [ + { + leftField: 'iso2', + right: { + id: '12345', + indexPatternId: 'apm_static_index_pattern_id', + indexPatternTitle: 'apm-*', + metrics: [ + { + field: 'transaction.duration.us', + type: 'avg', + }, + ], + term: 'client.geo.country_iso_code', + type: 'ES_TERM_SOURCE', + whereQuery: { + language: 'kuery', + query: 'processor.event:"transaction"', + }, + }, + }, + ], + label: '[Performance] Duration', + maxZoom: 24, + minZoom: 0, + sourceDescriptor: { + id: 'world_countries', + tooltipProperties: ['name', 'iso2'], + type: 'EMS_FILE', + }, + style: { + isTimeAware: true, + properties: { + fillColor: { + options: { + color: 'Green to Red', + colorCategory: 'palette_0', + field: { + name: '__kbnjoin__avg_of_transaction.duration.us__12345', + origin: 'join', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + type: 'ORDINAL', + }, + type: 'DYNAMIC', + }, + icon: { + options: { + value: 'marker', + }, + type: 'STATIC', + }, + iconOrientation: { + options: { + orientation: 0, + }, + type: 'STATIC', + }, + iconSize: { + options: { + size: 6, + }, + type: 'STATIC', + }, + labelText: { + options: { + value: '', + }, + type: 'STATIC', + }, + labelBorderColor: { + options: { + color: '#FFFFFF', + }, + type: 'STATIC', + }, + labelBorderSize: { + options: { + size: 'SMALL', + }, + }, + labelColor: { + options: { + color: '#000000', + }, + type: 'STATIC', + }, + labelSize: { + options: { + size: 14, + }, + type: 'STATIC', + }, + lineColor: { + options: { + color: '#3d3d3d', + }, + type: 'STATIC', + }, + lineWidth: { + options: { + size: 1, + }, + type: 'STATIC', + }, + symbolizeAs: { + options: { + value: 'circle', + }, + }, + }, + type: 'VECTOR', + }, + type: 'VECTOR', + visible: true, + }); + }); + + test('Should create heatmap layer descriptor when displayed as heatmap', () => { + const layerDescriptor = createLayerDescriptor({ + layer: OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE, + metric: OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION, + display: DISPLAY.HEATMAP, + }); + expect(layerDescriptor).toEqual({ + __dataRequests: [], + alpha: 0.75, + id: '12345', + joins: [], + label: '[Performance] Duration', + maxZoom: 24, + minZoom: 0, + query: { + language: 'kuery', + query: 'processor.event:"transaction"', + }, + sourceDescriptor: { + geoField: 'client.geo.location', + id: '12345', + indexPatternId: 'apm_static_index_pattern_id', + metrics: [ + { + field: 'transaction.duration.us', + type: 'avg', + }, + ], + requestType: 'heatmap', + resolution: 'MOST_FINE', + type: 'ES_GEO_GRID', + }, + style: { + colorRampName: 'theclassic', + type: 'HEATMAP', + }, + type: 'HEATMAP', + visible: true, + }); + }); + + test('Should create vector layer descriptor when displayed as clusters', () => { + const layerDescriptor = createLayerDescriptor({ + layer: OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE, + metric: OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION, + display: DISPLAY.CLUSTERS, + }); + expect(layerDescriptor).toEqual({ + __dataRequests: [], + alpha: 0.75, + id: '12345', + joins: [], + label: '[Performance] Duration', + maxZoom: 24, + minZoom: 0, + query: { + language: 'kuery', + query: 'processor.event:"transaction"', + }, + sourceDescriptor: { + geoField: 'client.geo.location', + id: '12345', + indexPatternId: 'apm_static_index_pattern_id', + metrics: [ + { + field: 'transaction.duration.us', + type: 'avg', + }, + ], + requestType: 'point', + resolution: 'MOST_FINE', + type: 'ES_GEO_GRID', + }, + style: { + isTimeAware: true, + properties: { + fillColor: { + options: { + color: 'Green to Red', + colorCategory: 'palette_0', + field: { + name: 'avg_of_transaction.duration.us', + origin: 'source', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + type: 'ORDINAL', + }, + type: 'DYNAMIC', + }, + icon: { + options: { + value: 'marker', + }, + type: 'STATIC', + }, + iconOrientation: { + options: { + orientation: 0, + }, + type: 'STATIC', + }, + iconSize: { + options: { + field: { + name: 'avg_of_transaction.duration.us', + origin: 'source', + }, + fieldMetaOptions: { + isEnabled: true, + sigma: 3, + }, + maxSize: 32, + minSize: 7, + }, + type: 'DYNAMIC', + }, + labelText: { + options: { + value: '', + }, + type: 'STATIC', + }, + labelBorderColor: { + options: { + color: '#FFFFFF', + }, + type: 'STATIC', + }, + labelBorderSize: { + options: { + size: 'SMALL', + }, + }, + labelColor: { + options: { + color: '#000000', + }, + type: 'STATIC', + }, + labelSize: { + options: { + size: 14, + }, + type: 'STATIC', + }, + lineColor: { + options: { + color: '#3d3d3d', + }, + type: 'STATIC', + }, + lineWidth: { + options: { + size: 1, + }, + type: 'STATIC', + }, + symbolizeAs: { + options: { + value: 'circle', + }, + }, + }, + type: 'VECTOR', + }, + type: 'VECTOR', + visible: true, + }); + }); +}); diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.ts b/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.ts new file mode 100644 index 0000000000000..a59122d7d6309 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/create_layer_descriptor.ts @@ -0,0 +1,270 @@ +/* + * 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 uuid from 'uuid/v4'; +import { i18n } from '@kbn/i18n'; +import { + AggDescriptor, + ColorDynamicOptions, + LabelDynamicOptions, + LayerDescriptor, + SizeDynamicOptions, + StylePropertyField, + VectorStylePropertiesDescriptor, +} from '../../../../common/descriptor_types'; +import { + AGG_TYPE, + COLOR_MAP_TYPE, + FIELD_ORIGIN, + GRID_RESOLUTION, + RENDER_AS, + SOURCE_TYPES, + STYLE_TYPE, + VECTOR_STYLES, +} from '../../../../common/constants'; +import { getJoinAggKey, getSourceAggKey } from '../../../../common/get_agg_key'; +import { OBSERVABILITY_LAYER_TYPE } from './layer_select'; +import { OBSERVABILITY_METRIC_TYPE } from './metric_select'; +import { DISPLAY } from './display_select'; +import { VectorStyle } from '../../styles/vector/vector_style'; +// @ts-ignore +import { EMSFileSource } from '../../sources/ems_file_source'; +// @ts-ignore +import { ESGeoGridSource } from '../../sources/es_geo_grid_source'; +import { VectorLayer } from '../../vector_layer'; +// @ts-ignore +import { HeatmapLayer } from '../../heatmap_layer'; +import { getDefaultDynamicProperties } from '../../styles/vector/vector_style_defaults'; + +// redefining APM constant to avoid making maps app depend on APM plugin +export const APM_INDEX_PATTERN_ID = 'apm_static_index_pattern_id'; + +const defaultDynamicProperties = getDefaultDynamicProperties(); + +function createDynamicFillColorDescriptor( + layer: OBSERVABILITY_LAYER_TYPE, + field: StylePropertyField +) { + return { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.FILL_COLOR]!.options as ColorDynamicOptions), + field, + color: + layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE ? 'Green to Red' : 'Yellow to Red', + type: COLOR_MAP_TYPE.ORDINAL, + }, + }; +} + +function createLayerLabel( + layer: OBSERVABILITY_LAYER_TYPE, + metric: OBSERVABILITY_METRIC_TYPE +): string | null { + let layerName; + if (layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE) { + layerName = i18n.translate('xpack.maps.observability.apmRumPerformanceLayerName', { + defaultMessage: 'Performance', + }); + } else if (layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_TRAFFIC) { + layerName = i18n.translate('xpack.maps.observability.apmRumTrafficLayerName', { + defaultMessage: 'Traffic', + }); + } + + let metricName; + if (metric === OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION) { + metricName = i18n.translate('xpack.maps.observability.durationMetricName', { + defaultMessage: 'Duration', + }); + } else if (metric === OBSERVABILITY_METRIC_TYPE.SLA_PERCENTAGE) { + metricName = i18n.translate('xpack.maps.observability.slaPercentageMetricName', { + defaultMessage: '% Duration of SLA', + }); + } else if (metric === OBSERVABILITY_METRIC_TYPE.COUNT) { + metricName = i18n.translate('xpack.maps.observability.countMetricName', { + defaultMessage: 'Total', + }); + } else if (metric === OBSERVABILITY_METRIC_TYPE.UNIQUE_COUNT) { + metricName = i18n.translate('xpack.maps.observability.uniqueCountMetricName', { + defaultMessage: 'Unique count', + }); + } + + return `[${layerName}] ${metricName}`; +} + +function createAggDescriptor(metric: OBSERVABILITY_METRIC_TYPE): AggDescriptor { + if (metric === OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION) { + return { + type: AGG_TYPE.AVG, + field: 'transaction.duration.us', + }; + } else if (metric === OBSERVABILITY_METRIC_TYPE.SLA_PERCENTAGE) { + return { + type: AGG_TYPE.AVG, + field: 'duration_sla_pct', + }; + } else if (metric === OBSERVABILITY_METRIC_TYPE.UNIQUE_COUNT) { + return { + type: AGG_TYPE.UNIQUE_COUNT, + field: 'transaction.id', + }; + } else { + return { type: AGG_TYPE.COUNT }; + } +} + +// All APM indices match APM index pattern. Need to apply query to filter to specific document types +// https://www.elastic.co/guide/en/kibana/current/apm-settings-kb.html +function createAmpSourceQuery(layer: OBSERVABILITY_LAYER_TYPE) { + // APM transaction documents + let query; + if ( + layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE || + layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_TRAFFIC + ) { + query = 'processor.event:"transaction"'; + } + + return query + ? { + language: 'kuery', + query, + } + : undefined; +} + +function getGeoGridRequestType(display: DISPLAY): RENDER_AS { + if (display === DISPLAY.HEATMAP) { + return RENDER_AS.HEATMAP; + } + + if (display === DISPLAY.GRIDS) { + return RENDER_AS.GRID; + } + + return RENDER_AS.POINT; +} + +export function createLayerDescriptor({ + layer, + metric, + display, +}: { + layer: OBSERVABILITY_LAYER_TYPE | null; + metric: OBSERVABILITY_METRIC_TYPE | null; + display: DISPLAY | null; +}): LayerDescriptor | null { + if (!layer || !metric || !display) { + return null; + } + + const apmSourceQuery = createAmpSourceQuery(layer); + const label = createLayerLabel(layer, metric); + const metricsDescriptor = createAggDescriptor(metric); + + if (display === DISPLAY.CHOROPLETH) { + const joinId = uuid(); + const joinKey = getJoinAggKey({ + aggType: metricsDescriptor.type, + aggFieldName: metricsDescriptor.field ? metricsDescriptor.field : '', + rightSourceId: joinId, + }); + return VectorLayer.createDescriptor({ + label, + joins: [ + { + leftField: 'iso2', + right: { + type: SOURCE_TYPES.ES_TERM_SOURCE, + id: joinId, + indexPatternId: APM_INDEX_PATTERN_ID, + indexPatternTitle: 'apm-*', // TODO look up from APM_OSS.indexPattern + term: 'client.geo.country_iso_code', + metrics: [metricsDescriptor], + whereQuery: apmSourceQuery, + }, + }, + ], + sourceDescriptor: EMSFileSource.createDescriptor({ + id: 'world_countries', + tooltipProperties: ['name', 'iso2'], + }), + style: VectorStyle.createDescriptor({ + [VECTOR_STYLES.FILL_COLOR]: createDynamicFillColorDescriptor(layer, { + name: joinKey, + origin: FIELD_ORIGIN.JOIN, + }), + [VECTOR_STYLES.LINE_COLOR]: { + type: STYLE_TYPE.STATIC, + options: { + color: '#3d3d3d', + }, + }, + }), + }); + } + + const geoGridSourceDescriptor = ESGeoGridSource.createDescriptor({ + indexPatternId: APM_INDEX_PATTERN_ID, + geoField: 'client.geo.location', + metrics: [metricsDescriptor], + requestType: getGeoGridRequestType(display), + resolution: GRID_RESOLUTION.MOST_FINE, + }); + + if (display === DISPLAY.HEATMAP) { + return HeatmapLayer.createDescriptor({ + label, + query: apmSourceQuery, + sourceDescriptor: geoGridSourceDescriptor, + }); + } + + const metricSourceKey = getSourceAggKey({ + aggType: metricsDescriptor.type, + aggFieldName: metricsDescriptor.field, + }); + const metricStyleField = { + name: metricSourceKey, + origin: FIELD_ORIGIN.SOURCE, + }; + + const styleProperties: VectorStylePropertiesDescriptor = { + [VECTOR_STYLES.FILL_COLOR]: createDynamicFillColorDescriptor(layer, metricStyleField), + [VECTOR_STYLES.ICON_SIZE]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE]!.options as SizeDynamicOptions), + field: metricStyleField, + }, + }, + [VECTOR_STYLES.LINE_COLOR]: { + type: STYLE_TYPE.STATIC, + options: { + color: '#3d3d3d', + }, + }, + }; + + if (metric === OBSERVABILITY_METRIC_TYPE.SLA_PERCENTAGE) { + styleProperties[VECTOR_STYLES.LABEL_TEXT] = { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.LABEL_TEXT]!.options as LabelDynamicOptions), + field: metricStyleField, + }, + }; + } + + return VectorLayer.createDescriptor({ + label, + query: apmSourceQuery, + sourceDescriptor: geoGridSourceDescriptor, + style: VectorStyle.createDescriptor(styleProperties), + }); +} diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/display_select.tsx b/x-pack/plugins/maps/public/layers/solution_layers/observability/display_select.tsx new file mode 100644 index 0000000000000..2c6d854db2fe9 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/display_select.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ChangeEvent } from 'react'; +import { EuiFormRow, EuiSelect } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { OBSERVABILITY_LAYER_TYPE } from './layer_select'; + +export enum DISPLAY { + CHOROPLETH = 'CHOROPLETH', + CLUSTERS = 'CLUSTERS', + GRIDS = 'GRIDS', + HEATMAP = 'HEATMAP', +} + +const DISPLAY_OPTIONS = [ + { + value: DISPLAY.CHOROPLETH, + text: i18n.translate('xpack.maps.observability.choroplethLabel', { + defaultMessage: 'World boundaries', + }), + }, + { + value: DISPLAY.CLUSTERS, + text: i18n.translate('xpack.maps.observability.clustersLabel', { + defaultMessage: 'Clusters', + }), + }, + { + value: DISPLAY.GRIDS, + text: i18n.translate('xpack.maps.observability.gridsLabel', { + defaultMessage: 'Grids', + }), + }, + { + value: DISPLAY.HEATMAP, + text: i18n.translate('xpack.maps.observability.heatMapLabel', { + defaultMessage: 'Heat map', + }), + }, +]; + +interface Props { + layer: OBSERVABILITY_LAYER_TYPE | null; + value: DISPLAY; + onChange: (display: DISPLAY) => void; +} + +export function DisplaySelect(props: Props) { + function onChange(event: ChangeEvent) { + props.onChange(event.target.value as DISPLAY); + } + + if (!props.layer) { + return null; + } + + return ( + + + + ); +} diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/index.ts b/x-pack/plugins/maps/public/layers/solution_layers/observability/index.ts new file mode 100644 index 0000000000000..ae6ade86de980 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { ObservabilityLayerWizardConfig } from './observability_layer_wizard'; diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/layer_select.tsx b/x-pack/plugins/maps/public/layers/solution_layers/observability/layer_select.tsx new file mode 100644 index 0000000000000..1c03cb419a849 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/layer_select.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ChangeEvent } from 'react'; +import { EuiFormRow, EuiSelect } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export enum OBSERVABILITY_LAYER_TYPE { + APM_RUM_PERFORMANCE = 'APM_RUM_PERFORMANCE', + APM_RUM_TRAFFIC = 'APM_RUM_TRAFFIC', +} + +const OBSERVABILITY_LAYER_OPTIONS = [ + { + value: OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE, + text: i18n.translate('xpack.maps.observability.apmRumPerformanceLabel', { + defaultMessage: 'APM RUM Performance', + }), + }, + { + value: OBSERVABILITY_LAYER_TYPE.APM_RUM_TRAFFIC, + text: i18n.translate('xpack.maps.observability.apmRumTrafficLabel', { + defaultMessage: 'APM RUM Traffic', + }), + }, +]; + +interface Props { + value: OBSERVABILITY_LAYER_TYPE | null; + onChange: (layer: OBSERVABILITY_LAYER_TYPE) => void; +} + +export function LayerSelect(props: Props) { + function onChange(event: ChangeEvent) { + props.onChange(event.target.value as OBSERVABILITY_LAYER_TYPE); + } + + const options = props.value + ? OBSERVABILITY_LAYER_OPTIONS + : [{ value: '', text: '' }, ...OBSERVABILITY_LAYER_OPTIONS]; + + return ( + + + + ); +} diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/metric_select.tsx b/x-pack/plugins/maps/public/layers/solution_layers/observability/metric_select.tsx new file mode 100644 index 0000000000000..8750034f74696 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/metric_select.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { ChangeEvent } from 'react'; +import { EuiFormRow, EuiSelect, EuiSelectOption } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { OBSERVABILITY_LAYER_TYPE } from './layer_select'; + +export enum OBSERVABILITY_METRIC_TYPE { + TRANSACTION_DURATION = 'TRANSACTION_DURATION', + SLA_PERCENTAGE = 'SLA_PERCENTAGE', + COUNT = 'COUNT', + UNIQUE_COUNT = 'UNIQUE_COUNT', +} + +const APM_RUM_PERFORMANCE_METRIC_OPTIONS = [ + { + value: OBSERVABILITY_METRIC_TYPE.TRANSACTION_DURATION, + text: i18n.translate('xpack.maps.observability.transactionDurationLabel', { + defaultMessage: 'Transaction duraction', + }), + }, + { + value: OBSERVABILITY_METRIC_TYPE.SLA_PERCENTAGE, + text: i18n.translate('xpack.maps.observability.slaPercentageLabel', { + defaultMessage: 'SLA percentage', + }), + }, +]; + +const APM_RUM_TRAFFIC_METRIC_OPTIONS = [ + { + value: OBSERVABILITY_METRIC_TYPE.COUNT, + text: i18n.translate('xpack.maps.observability.countLabel', { + defaultMessage: 'Count', + }), + }, + { + value: OBSERVABILITY_METRIC_TYPE.UNIQUE_COUNT, + text: i18n.translate('xpack.maps.observability.uniqueCountLabel', { + defaultMessage: 'Unique count', + }), + }, +]; + +export function getMetricOptionsForLayer(layer: OBSERVABILITY_LAYER_TYPE): EuiSelectOption[] { + if (layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_PERFORMANCE) { + return APM_RUM_PERFORMANCE_METRIC_OPTIONS; + } + + if (layer === OBSERVABILITY_LAYER_TYPE.APM_RUM_TRAFFIC) { + return APM_RUM_TRAFFIC_METRIC_OPTIONS; + } + + return []; +} + +interface Props { + layer: OBSERVABILITY_LAYER_TYPE | null; + value: OBSERVABILITY_METRIC_TYPE | null; + onChange: (metricType: OBSERVABILITY_METRIC_TYPE) => void; +} + +export function MetricSelect(props: Props) { + function onChange(event: ChangeEvent) { + props.onChange(event.target.value as OBSERVABILITY_METRIC_TYPE); + } + + if (!props.layer || !props.value) { + return null; + } + + return ( + + + + ); +} diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_template.tsx b/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_template.tsx new file mode 100644 index 0000000000000..7326f8459b5c7 --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_template.tsx @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Component, Fragment } from 'react'; +import { RenderWizardArguments } from '../../layer_wizard_registry'; +import { LayerSelect, OBSERVABILITY_LAYER_TYPE } from './layer_select'; +import { getMetricOptionsForLayer, MetricSelect, OBSERVABILITY_METRIC_TYPE } from './metric_select'; +import { DisplaySelect, DISPLAY } from './display_select'; +import { createLayerDescriptor } from './create_layer_descriptor'; + +interface State { + display: DISPLAY; + layer: OBSERVABILITY_LAYER_TYPE | null; + metric: OBSERVABILITY_METRIC_TYPE | null; +} + +export class ObservabilityLayerTemplate extends Component { + state = { + layer: null, + metric: null, + display: DISPLAY.CHOROPLETH, + }; + + _onLayerChange = (layer: OBSERVABILITY_LAYER_TYPE) => { + const newState = { layer, metric: this.state.metric }; + + // Select metric when layer change invalidates selected metric. + const metricOptions = getMetricOptionsForLayer(layer); + const selectedMetricOption = metricOptions.find(option => { + return option.value === this.state.metric; + }); + if (!selectedMetricOption) { + if (metricOptions.length) { + // @ts-ignore + newState.metric = metricOptions[0].value; + } else { + newState.metric = null; + } + } + + this.setState(newState, this._previewLayer); + }; + + _onMetricChange = (metric: OBSERVABILITY_METRIC_TYPE) => { + this.setState({ metric }, this._previewLayer); + }; + + _onDisplayChange = (display: DISPLAY) => { + this.setState({ display }, this._previewLayer); + }; + + _previewLayer() { + this.props.previewLayer( + createLayerDescriptor({ + layer: this.state.layer, + metric: this.state.metric, + display: this.state.display, + }) + ); + } + + render() { + return ( + + + + + + ); + } +} diff --git a/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_wizard.tsx b/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_wizard.tsx new file mode 100644 index 0000000000000..3fbb3157ae62a --- /dev/null +++ b/x-pack/plugins/maps/public/layers/solution_layers/observability/observability_layer_wizard.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { LayerWizard, RenderWizardArguments } from '../../layer_wizard_registry'; +import { ObservabilityLayerTemplate } from './observability_layer_template'; +import { APM_INDEX_PATTERN_ID } from './create_layer_descriptor'; +import { getIndexPatternService } from '../../../kibana_services'; + +export const ObservabilityLayerWizardConfig: LayerWizard = { + checkVisibility: async () => { + try { + await getIndexPatternService().get(APM_INDEX_PATTERN_ID); + return true; + } catch (e) { + return false; + } + }, + description: i18n.translate('xpack.maps.observability.desc', { + defaultMessage: 'APM layers', + }), + icon: 'logoObservability', + renderWizard: (renderWizardArguments: RenderWizardArguments) => { + return ; + }, + title: i18n.translate('xpack.maps.observability.title', { + defaultMessage: 'Observability', + }), +}; diff --git a/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js index 58c56fe32f766..22c8293132b42 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_agg_source/es_agg_source.js @@ -7,13 +7,8 @@ import { i18n } from '@kbn/i18n'; import { AbstractESSource } from '../es_source'; import { esAggFieldsFactory } from '../../fields/es_agg_field'; -import { - AGG_DELIMITER, - AGG_TYPE, - COUNT_PROP_LABEL, - COUNT_PROP_NAME, - FIELD_ORIGIN, -} from '../../../../common/constants'; +import { AGG_TYPE, COUNT_PROP_LABEL, FIELD_ORIGIN } from '../../../../common/constants'; +import { getSourceAggKey } from '../../../../common/get_agg_key'; export class AbstractESAggSource extends AbstractESSource { constructor(descriptor, inspectorAdapters) { @@ -59,7 +54,10 @@ export class AbstractESAggSource extends AbstractESSource { } getAggKey(aggType, fieldName) { - return aggType !== AGG_TYPE.COUNT ? `${aggType}${AGG_DELIMITER}${fieldName}` : COUNT_PROP_NAME; + return getSourceAggKey({ + aggType, + aggFieldName: fieldName, + }); } getAggLabel(aggType, fieldName) { diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js index 17fad2f2e6453..053af4bfebe61 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/es_geo_grid_source.js @@ -35,13 +35,14 @@ export const heatmapTitle = i18n.translate('xpack.maps.source.esGridHeatmapTitle export class ESGeoGridSource extends AbstractESAggSource { static type = SOURCE_TYPES.ES_GEO_GRID; - static createDescriptor({ indexPatternId, geoField, requestType, resolution }) { + static createDescriptor({ indexPatternId, geoField, metrics, requestType, resolution }) { return { type: ESGeoGridSource.type, id: uuid(), - indexPatternId: indexPatternId, - geoField: geoField, - requestType: requestType, + indexPatternId, + geoField, + metrics: metrics ? metrics : [], + requestType, resolution: resolution ? resolution : GRID_RESOLUTION.COARSE, }; } diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/scaling_form.tsx b/x-pack/plugins/maps/public/layers/sources/es_search_source/scaling_form.tsx index d86fc6d4026e6..829c9a1ce439d 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/scaling_form.tsx +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/scaling_form.tsx @@ -18,9 +18,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; // @ts-ignore import { SingleFieldSelect } from '../../../components/single_field_select'; - -// @ts-ignore -import { indexPatternService } from '../../../kibana_services'; +import { getIndexPatternService } from '../../../kibana_services'; // @ts-ignore import { ValidatedRange } from '../../../components/validated_range'; import { @@ -68,8 +66,10 @@ export class ScalingForm extends Component { async loadIndexSettings() { try { - const indexPattern = await indexPatternService.get(this.props.indexPatternId); - const { maxInnerResultWindow, maxResultWindow } = await loadIndexSettings(indexPattern.title); + const indexPattern = await getIndexPatternService().get(this.props.indexPatternId); + const { maxInnerResultWindow, maxResultWindow } = await loadIndexSettings( + indexPattern!.title + ); if (this._isMounted) { this.setState({ maxInnerResultWindow, maxResultWindow }); } diff --git a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js index cb07bb0e7d2ed..a6c4afa71dbb2 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_term_source/es_term_source.js @@ -7,8 +7,13 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { AGG_TYPE, DEFAULT_MAX_BUCKETS_LIMIT, FIELD_ORIGIN } from '../../../../common/constants'; -import { getJoinAggKey } from '../../../../common/get_join_key'; +import { + AGG_TYPE, + DEFAULT_MAX_BUCKETS_LIMIT, + FIELD_ORIGIN, + SOURCE_TYPES, +} from '../../../../common/constants'; +import { getJoinAggKey } from '../../../../common/get_agg_key'; import { ESDocField } from '../../fields/es_doc_field'; import { AbstractESAggSource } from '../es_agg_source'; import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils'; @@ -30,7 +35,7 @@ export function extractPropertiesMap(rawEsData, countPropertyName) { } export class ESTermSource extends AbstractESAggSource { - static type = 'ES_TERM_SOURCE'; + static type = SOURCE_TYPES.ES_TERM_SOURCE; constructor(descriptor, inspectorAdapters) { super(descriptor, inspectorAdapters); diff --git a/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx b/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx index 141fabeedd3e5..3b4015641ede9 100644 --- a/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/layers/sources/kibana_tilemap_source/kibana_base_map_layer_wizard.tsx @@ -16,7 +16,7 @@ import { TileLayer } from '../../tile_layer'; import { getKibanaTileMap } from '../../../meta'; export const kibanaBasemapLayerWizardConfig: LayerWizard = { - checkVisibility: () => { + checkVisibility: async () => { const tilemap = getKibanaTileMap(); return !!tilemap.url; }, diff --git a/x-pack/plugins/maps/public/layers/vector_layer.d.ts b/x-pack/plugins/maps/public/layers/vector_layer.d.ts index efc1f3011c687..710b95b045e71 100644 --- a/x-pack/plugins/maps/public/layers/vector_layer.d.ts +++ b/x-pack/plugins/maps/public/layers/vector_layer.d.ts @@ -9,7 +9,6 @@ import { AbstractLayer } from './layer'; import { IVectorSource } from './sources/vector_source'; import { MapFilters, - LayerDescriptor, VectorLayerDescriptor, VectorSourceRequestMeta, } from '../../common/descriptor_types'; @@ -35,7 +34,7 @@ export interface IVectorLayer extends ILayer { export class VectorLayer extends AbstractLayer implements IVectorLayer { protected readonly _style: IVectorStyle; static createDescriptor( - options: Partial, + options: Partial, mapColors?: string[] ): VectorLayerDescriptor; From 76d8ffe0cd218a44c96ca7e96fe5f1d8c462d63a Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 5 May 2020 11:54:21 -0700 Subject: [PATCH 23/72] [Reporting] Convert test code to Typescript (#65155) * convert tests to typescript * comment note * add type for api integration test * fix import --- .../{chromium_tests.js => chromium_tests.ts} | 6 +- .../api/{constants.js => constants.ts} | 0 .../api/generate/{index.js => index.ts} | 5 +- ...{generation_urls.js => generation_urls.ts} | 0 .../test/reporting/api/{usage.js => usage.ts} | 15 +++-- .../index.js => ftr_provider_context.d.ts} | 6 +- x-pack/test/reporting/services/index.ts | 15 +++++ .../{reporting_api.js => reporting_api.ts} | 61 ++++++++++++++----- 8 files changed, 84 insertions(+), 24 deletions(-) rename x-pack/test/reporting/api/{chromium_tests.js => chromium_tests.ts} (77%) rename x-pack/test/reporting/api/{constants.js => constants.ts} (100%) rename x-pack/test/reporting/api/generate/{index.js => index.ts} (69%) rename x-pack/test/reporting/api/{generation_urls.js => generation_urls.ts} (100%) rename x-pack/test/reporting/api/{usage.js => usage.ts} (93%) rename x-pack/test/reporting/{services/index.js => ftr_provider_context.d.ts} (56%) create mode 100644 x-pack/test/reporting/services/index.ts rename x-pack/test/reporting/services/{reporting_api.js => reporting_api.ts} (68%) diff --git a/x-pack/test/reporting/api/chromium_tests.js b/x-pack/test/reporting/api/chromium_tests.ts similarity index 77% rename from x-pack/test/reporting/api/chromium_tests.js rename to x-pack/test/reporting/api/chromium_tests.ts index 2d5a31bb40da3..75e8e3e70b5a5 100644 --- a/x-pack/test/reporting/api/chromium_tests.js +++ b/x-pack/test/reporting/api/chromium_tests.ts @@ -4,9 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -import { OSS_KIBANA_ARCHIVE_PATH, OSS_DATA_ARCHIVE_PATH } from './constants'; +import { OSS_DATA_ARCHIVE_PATH, OSS_KIBANA_ARCHIVE_PATH } from './constants'; +import { FtrProviderContext } from '../ftr_provider_context'; -export default function({ loadTestFile, getService }) { +// eslint-disable-next-line import/no-default-export +export default function({ loadTestFile, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); diff --git a/x-pack/test/reporting/api/constants.js b/x-pack/test/reporting/api/constants.ts similarity index 100% rename from x-pack/test/reporting/api/constants.js rename to x-pack/test/reporting/api/constants.ts diff --git a/x-pack/test/reporting/api/generate/index.js b/x-pack/test/reporting/api/generate/index.ts similarity index 69% rename from x-pack/test/reporting/api/generate/index.js rename to x-pack/test/reporting/api/generate/index.ts index 3e5f2d1fc1eb3..b9db0d465d005 100644 --- a/x-pack/test/reporting/api/generate/index.js +++ b/x-pack/test/reporting/api/generate/index.ts @@ -4,7 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -export default function({ loadTestFile }) { +import { FtrProviderContext } from '../../ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function({ loadTestFile }: FtrProviderContext) { describe('CSV', function() { this.tags('ciGroup2'); loadTestFile(require.resolve('./csv_saved_search')); diff --git a/x-pack/test/reporting/api/generation_urls.js b/x-pack/test/reporting/api/generation_urls.ts similarity index 100% rename from x-pack/test/reporting/api/generation_urls.js rename to x-pack/test/reporting/api/generation_urls.ts diff --git a/x-pack/test/reporting/api/usage.js b/x-pack/test/reporting/api/usage.ts similarity index 93% rename from x-pack/test/reporting/api/usage.js rename to x-pack/test/reporting/api/usage.ts index c1005c441f463..e3ebcf9d3bab0 100644 --- a/x-pack/test/reporting/api/usage.js +++ b/x-pack/test/reporting/api/usage.ts @@ -5,22 +5,29 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; +import { ReportingUsageStats } from '../services/reporting_api'; import * as GenerationUrls from './generation_urls'; -export default function({ getService }) { +interface UsageStats { + reporting: ReportingUsageStats; +} + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const reportingAPI = getService('reportingAPI'); - const usageAPI = getService('usageAPI'); + const usageAPI = getService('usageAPI' as any); // NOTE Usage API service is not Typescript describe('reporting usage', () => { before(() => reportingAPI.deleteAllReportingIndexes()); afterEach(() => reportingAPI.deleteAllReportingIndexes()); describe('initial state', () => { - let usage; + let usage: UsageStats; before(async () => { - usage = await usageAPI.getUsageStats(); + usage = (await usageAPI.getUsageStats()) as UsageStats; }); it('shows reporting as available and enabled', async () => { diff --git a/x-pack/test/reporting/services/index.js b/x-pack/test/reporting/ftr_provider_context.d.ts similarity index 56% rename from x-pack/test/reporting/services/index.js rename to x-pack/test/reporting/ftr_provider_context.d.ts index d181e24442d2d..e3add3748f56d 100644 --- a/x-pack/test/reporting/services/index.js +++ b/x-pack/test/reporting/ftr_provider_context.d.ts @@ -4,4 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -export { ReportingAPIProvider } from './reporting_api'; +import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; + +import { services } from './services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/reporting/services/index.ts b/x-pack/test/reporting/services/index.ts new file mode 100644 index 0000000000000..9684f2a8abc6c --- /dev/null +++ b/x-pack/test/reporting/services/index.ts @@ -0,0 +1,15 @@ +/* + * 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 { ReportingAPIProvider } from './reporting_api'; +import { services as xpackServices } from '../../functional/services'; + +export const services = { + ...xpackServices, + reportingAPI: ReportingAPIProvider, +}; + +export { ReportingAPIProvider }; diff --git a/x-pack/test/reporting/services/reporting_api.js b/x-pack/test/reporting/services/reporting_api.ts similarity index 68% rename from x-pack/test/reporting/services/reporting_api.js rename to x-pack/test/reporting/services/reporting_api.ts index 82fe6aea08ac3..1fa5fd7135708 100644 --- a/x-pack/test/reporting/services/reporting_api.js +++ b/x-pack/test/reporting/services/reporting_api.ts @@ -5,28 +5,57 @@ */ import expect from '@kbn/expect'; +// @ts-ignore no module definition import { indexTimestamp } from '../../../legacy/plugins/reporting/server/lib/esqueue/helpers/index_timestamp'; +import { FtrProviderContext } from '../ftr_provider_context'; -function removeWhitespace(str) { +interface PDFAppCounts { + app: { + [appName: string]: number; + }; + layout: { + [layoutType: string]: number; + }; +} + +export interface ReportingUsageStats { + available: boolean; + enabled: boolean; + total: number; + last_7_days: { + total: number; + printable_pdf: PDFAppCounts; + [jobType: string]: any; + }; + printable_pdf: PDFAppCounts; + status: any; + [jobType: string]: any; +} + +interface UsageStats { + reporting: ReportingUsageStats; +} + +function removeWhitespace(str: string) { return str.replace(/\s/g, ''); } -export function ReportingAPIProvider({ getService }) { +export function ReportingAPIProvider({ getService }: FtrProviderContext) { const log = getService('log'); const supertest = getService('supertest'); const esSupertest = getService('esSupertest'); return { - async waitForJobToFinish(downloadReportPath) { + async waitForJobToFinish(downloadReportPath: string) { log.debug(`Waiting for job to finish: ${downloadReportPath}`); const JOB_IS_PENDING_CODE = 503; const statusCode = await new Promise(resolve => { const intervalId = setInterval(async () => { - const response = await supertest + const response = (await supertest .get(downloadReportPath) .responseType('blob') - .set('kbn-xsrf', 'xxx'); + .set('kbn-xsrf', 'xxx')) as any; log.debug(`Report at path ${downloadReportPath} returned code ${response.statusCode}`); if (response.statusCode !== JOB_IS_PENDING_CODE) { clearInterval(intervalId); @@ -38,7 +67,7 @@ export function ReportingAPIProvider({ getService }) { expect(statusCode).to.be(200); }, - async expectAllJobsToFinishSuccessfully(jobPaths) { + async expectAllJobsToFinishSuccessfully(jobPaths: string[]) { await Promise.all( jobPaths.map(async path => { await this.waitForJobToFinish(path); @@ -46,7 +75,7 @@ export function ReportingAPIProvider({ getService }) { ); }, - async postJob(apiPath) { + async postJob(apiPath: string) { log.debug(`ReportingAPI.postJob(${apiPath})`); const { body } = await supertest .post(removeWhitespace(apiPath)) @@ -59,7 +88,7 @@ export function ReportingAPIProvider({ getService }) { * * @return {Promise} A function to call to clean up the index alias that was added. */ - async coerceReportsIntoExistingIndex(indexName) { + async coerceReportsIntoExistingIndex(indexName: string) { log.debug(`ReportingAPI.coerceReportsIntoExistingIndex(${indexName})`); // Adding an index alias coerces the report to be generated on an existing index which means any new @@ -96,35 +125,35 @@ export function ReportingAPIProvider({ getService }) { await esSupertest.delete('/.reporting*').expect(200); }, - expectRecentPdfAppStats(stats, app, count) { + expectRecentPdfAppStats(stats: UsageStats, app: string, count: number) { expect(stats.reporting.last_7_days.printable_pdf.app[app]).to.be(count); }, - expectAllTimePdfAppStats(stats, app, count) { + expectAllTimePdfAppStats(stats: UsageStats, app: string, count: number) { expect(stats.reporting.printable_pdf.app[app]).to.be(count); }, - expectRecentPdfLayoutStats(stats, layout, count) { + expectRecentPdfLayoutStats(stats: UsageStats, layout: string, count: number) { expect(stats.reporting.last_7_days.printable_pdf.layout[layout]).to.be(count); }, - expectAllTimePdfLayoutStats(stats, layout, count) { + expectAllTimePdfLayoutStats(stats: UsageStats, layout: string, count: number) { expect(stats.reporting.printable_pdf.layout[layout]).to.be(count); }, - expectRecentJobTypeTotalStats(stats, jobType, count) { + expectRecentJobTypeTotalStats(stats: UsageStats, jobType: string, count: number) { expect(stats.reporting.last_7_days[jobType].total).to.be(count); }, - expectAllTimeJobTypeTotalStats(stats, jobType, count) { + expectAllTimeJobTypeTotalStats(stats: UsageStats, jobType: string, count: number) { expect(stats.reporting[jobType].total).to.be(count); }, - getCompletedReportCount(stats) { + getCompletedReportCount(stats: UsageStats) { return stats.reporting.status.completed; }, - expectCompletedReportCount(stats, count) { + expectCompletedReportCount(stats: UsageStats, count: number) { expect(this.getCompletedReportCount(stats)).to.be(count); }, }; From a467fe5ffd53a65606ab22541bea3c7a143e8a84 Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Tue, 5 May 2020 13:57:25 -0500 Subject: [PATCH 24/72] [Metrics UI] Debounce onChange in alert creation UI (#65167) --- .../alerting/metric_threshold/components/expression.tsx | 9 ++++++++- .../public/components/alerting/inventory/expression.tsx | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx index c1213b8ddfa1c..406f9c7602d35 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { debounce } from 'lodash'; import React, { ChangeEvent, useCallback, useMemo, useEffect, useState } from 'react'; import { EuiSpacer, @@ -40,6 +41,8 @@ import { ExpressionRow } from './expression_row'; import { AlertContextMeta, TimeUnit, MetricExpression } from '../types'; import { ExpressionChart } from './expression_chart'; +const FILTER_TYPING_DEBOUNCE_MS = 500; + interface Props { errors: IErrorObject[]; alertParams: { @@ -125,6 +128,10 @@ export const Expressions: React.FC = props => { [setAlertParams, derivedIndexPattern] ); + const debouncedOnFilterChange = useCallback(debounce(onFilterChange, FILTER_TYPING_DEBOUNCE_MS), [ + onFilterChange, + ]); + const onGroupByChange = useCallback( (group: string | null) => { setAlertParams('groupBy', group || ''); @@ -320,7 +327,7 @@ export const Expressions: React.FC = props => { {(alertsContext.metadata && ( diff --git a/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx b/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx index 15cad770836bd..c2ee552e31553 100644 --- a/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx +++ b/x-pack/plugins/infra/public/components/alerting/inventory/expression.tsx @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { debounce } from 'lodash'; import React, { useCallback, useMemo, useEffect, useState, ChangeEvent } from 'react'; import { EuiFlexGroup, @@ -51,6 +52,8 @@ import { NodeTypeExpression } from './node_type'; import { InfraWaffleMapOptions } from '../../../lib/lib'; import { convertKueryToElasticSearchQuery } from '../../../utils/kuery'; +const FILTER_TYPING_DEBOUNCE_MS = 500; + interface AlertContextMeta { options?: Partial; nodeType?: InventoryItemType; @@ -134,6 +137,10 @@ export const Expressions: React.FC = props => { [derivedIndexPattern, setAlertParams] ); + const debouncedOnFilterChange = useCallback(debounce(onFilterChange, FILTER_TYPING_DEBOUNCE_MS), [ + onFilterChange, + ]); + const emptyError = useMemo(() => { return { aggField: [], @@ -291,7 +298,7 @@ export const Expressions: React.FC = props => { )) || ( From 2ccc397fe778058530f1af56b793e820a7efedba Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Tue, 5 May 2020 21:59:58 +0300 Subject: [PATCH 25/72] [data.search.aggs]: Expression functions for metric agg types (#64914) --- .../data/public/search/aggs/agg_types.ts | 44 ++++++ .../data/public/search/aggs/metrics/avg.ts | 5 + .../public/search/aggs/metrics/avg_fn.test.ts | 64 +++++++++ .../data/public/search/aggs/metrics/avg_fn.ts | 95 +++++++++++++ .../public/search/aggs/metrics/bucket_avg.ts | 6 + .../search/aggs/metrics/bucket_avg_fn.test.ts | 78 +++++++++++ .../search/aggs/metrics/bucket_avg_fn.ts | 107 ++++++++++++++ .../public/search/aggs/metrics/bucket_max.ts | 6 + .../search/aggs/metrics/bucket_max_fn.test.ts | 78 +++++++++++ .../search/aggs/metrics/bucket_max_fn.ts | 107 ++++++++++++++ .../public/search/aggs/metrics/bucket_min.ts | 6 + .../search/aggs/metrics/bucket_min_fn.test.ts | 78 +++++++++++ .../search/aggs/metrics/bucket_min_fn.ts | 107 ++++++++++++++ .../public/search/aggs/metrics/bucket_sum.ts | 6 + .../search/aggs/metrics/bucket_sum_fn.test.ts | 78 +++++++++++ .../search/aggs/metrics/bucket_sum_fn.ts | 107 ++++++++++++++ .../public/search/aggs/metrics/cardinality.ts | 5 + .../aggs/metrics/cardinality_fn.test.ts | 64 +++++++++ .../search/aggs/metrics/cardinality_fn.ts | 95 +++++++++++++ .../search/aggs/metrics/count_fn.test.ts | 59 ++++++++ .../public/search/aggs/metrics/count_fn.ts | 88 ++++++++++++ .../search/aggs/metrics/cumulative_sum.ts | 7 + .../aggs/metrics/cumulative_sum_fn.test.ts | 120 ++++++++++++++++ .../search/aggs/metrics/cumulative_sum_fn.ts | 111 +++++++++++++++ .../public/search/aggs/metrics/derivative.ts | 7 + .../search/aggs/metrics/derivative_fn.test.ts | 120 ++++++++++++++++ .../search/aggs/metrics/derivative_fn.ts | 111 +++++++++++++++ .../public/search/aggs/metrics/geo_bounds.ts | 5 + .../search/aggs/metrics/geo_bounds_fn.test.ts | 64 +++++++++ .../search/aggs/metrics/geo_bounds_fn.ts | 95 +++++++++++++ .../search/aggs/metrics/geo_centroid.ts | 5 + .../aggs/metrics/geo_centroid_fn.test.ts | 64 +++++++++ .../search/aggs/metrics/geo_centroid_fn.ts | 95 +++++++++++++ .../data/public/search/aggs/metrics/index.ts | 20 +++ .../data/public/search/aggs/metrics/max.ts | 5 + .../public/search/aggs/metrics/max_fn.test.ts | 64 +++++++++ .../data/public/search/aggs/metrics/max_fn.ts | 95 +++++++++++++ .../data/public/search/aggs/metrics/median.ts | 5 + .../search/aggs/metrics/median_fn.test.ts | 64 +++++++++ .../public/search/aggs/metrics/median_fn.ts | 95 +++++++++++++ .../data/public/search/aggs/metrics/min.ts | 5 + .../public/search/aggs/metrics/min_fn.test.ts | 64 +++++++++ .../data/public/search/aggs/metrics/min_fn.ts | 95 +++++++++++++ .../public/search/aggs/metrics/moving_avg.ts | 9 ++ .../search/aggs/metrics/moving_avg_fn.test.ts | 130 ++++++++++++++++++ .../search/aggs/metrics/moving_avg_fn.ts | 124 +++++++++++++++++ .../search/aggs/metrics/percentile_ranks.ts | 6 + .../aggs/metrics/percentile_ranks_fn.test.ts | 93 +++++++++++++ .../aggs/metrics/percentile_ranks_fn.ts | 102 ++++++++++++++ .../public/search/aggs/metrics/percentiles.ts | 6 + .../aggs/metrics/percentiles_fn.test.ts | 93 +++++++++++++ .../search/aggs/metrics/percentiles_fn.ts | 102 ++++++++++++++ .../public/search/aggs/metrics/serial_diff.ts | 7 + .../aggs/metrics/serial_diff_fn.test.ts | 120 ++++++++++++++++ .../search/aggs/metrics/serial_diff_fn.ts | 111 +++++++++++++++ .../search/aggs/metrics/std_deviation.ts | 5 + .../aggs/metrics/std_deviation_fn.test.ts | 64 +++++++++ .../search/aggs/metrics/std_deviation_fn.ts | 95 +++++++++++++ .../data/public/search/aggs/metrics/sum.ts | 5 + .../public/search/aggs/metrics/sum_fn.test.ts | 64 +++++++++ .../data/public/search/aggs/metrics/sum_fn.ts | 95 +++++++++++++ .../public/search/aggs/metrics/top_hit.ts | 9 ++ .../search/aggs/metrics/top_hit_fn.test.ts | 102 ++++++++++++++ .../public/search/aggs/metrics/top_hit_fn.ts | 122 ++++++++++++++++ src/plugins/data/public/search/aggs/types.ts | 42 ++++++ 65 files changed, 4105 insertions(+) create mode 100644 src/plugins/data/public/search/aggs/metrics/avg_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/avg_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_max_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_max_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_min_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_min_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/cardinality_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/cardinality_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/count_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/count_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/derivative_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/derivative_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/max_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/max_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/median_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/median_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/min_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/min_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/moving_avg_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/moving_avg_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/percentiles_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/percentiles_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/serial_diff_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/serial_diff_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/std_deviation_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/std_deviation_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/sum_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/sum_fn.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/top_hit_fn.test.ts create mode 100644 src/plugins/data/public/search/aggs/metrics/top_hit_fn.ts diff --git a/src/plugins/data/public/search/aggs/agg_types.ts b/src/plugins/data/public/search/aggs/agg_types.ts index 7c7d7609cc82f..2af29d3600246 100644 --- a/src/plugins/data/public/search/aggs/agg_types.ts +++ b/src/plugins/data/public/search/aggs/agg_types.ts @@ -118,7 +118,51 @@ import { aggHistogram } from './buckets/histogram_fn'; import { aggDateHistogram } from './buckets/date_histogram_fn'; import { aggTerms } from './buckets/terms_fn'; +/** Metrics: **/ +import { aggAvg } from './metrics/avg_fn'; +import { aggBucketAvg } from './metrics/bucket_avg_fn'; +import { aggBucketMax } from './metrics/bucket_max_fn'; +import { aggBucketMin } from './metrics/bucket_min_fn'; +import { aggBucketSum } from './metrics/bucket_sum_fn'; +import { aggCardinality } from './metrics/cardinality_fn'; +import { aggCount } from './metrics/count_fn'; +import { aggCumulativeSum } from './metrics/cumulative_sum_fn'; +import { aggDerivative } from './metrics/derivative_fn'; +import { aggGeoBounds } from './metrics/geo_bounds_fn'; +import { aggGeoCentroid } from './metrics/geo_centroid_fn'; +import { aggMax } from './metrics/max_fn'; +import { aggMedian } from './metrics/median_fn'; +import { aggMin } from './metrics/min_fn'; +import { aggMovingAvg } from './metrics/moving_avg_fn'; +import { aggPercentileRanks } from './metrics/percentile_ranks_fn'; +import { aggPercentiles } from './metrics/percentiles_fn'; +import { aggSerialDiff } from './metrics/serial_diff_fn'; +import { aggStdDeviation } from './metrics/std_deviation_fn'; +import { aggSum } from './metrics/sum_fn'; +import { aggTopHit } from './metrics/top_hit_fn'; + export const getAggTypesFunctions = () => [ + aggAvg, + aggBucketAvg, + aggBucketMax, + aggBucketMin, + aggBucketSum, + aggCardinality, + aggCount, + aggCumulativeSum, + aggDerivative, + aggGeoBounds, + aggGeoCentroid, + aggMax, + aggMedian, + aggMin, + aggMovingAvg, + aggPercentileRanks, + aggPercentiles, + aggSerialDiff, + aggStdDeviation, + aggSum, + aggTopHit, aggFilter, aggFilters, aggSignificantTerms, diff --git a/src/plugins/data/public/search/aggs/metrics/avg.ts b/src/plugins/data/public/search/aggs/metrics/avg.ts index d53ce8d3fc489..96be3e849a3e8 100644 --- a/src/plugins/data/public/search/aggs/metrics/avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/avg.ts @@ -22,11 +22,16 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const averageTitle = i18n.translate('data.search.aggs.metrics.averageTitle', { defaultMessage: 'Average', }); +export interface AggParamsAvg extends BaseAggParams { + field: string; +} + export interface AvgMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/avg_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/avg_fn.test.ts new file mode 100644 index 0000000000000..0e2ee00df49dd --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/avg_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggAvg } from './avg_fn'; + +describe('agg_expression_functions', () => { + describe('aggAvg', () => { + const fn = functionWrapper(aggAvg()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "avg", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/avg_fn.ts b/src/plugins/data/public/search/aggs/metrics/avg_fn.ts new file mode 100644 index 0000000000000..c370623b2752a --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/avg_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggAvg'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggAvg = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.avg.help', { + defaultMessage: 'Generates a serialized agg config for a Avg agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.avg.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.avg.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.avg.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.avg.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.avg.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.avg.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.AVG, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts index 2c32ebc671539..ded17eebf465b 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_avg.ts @@ -23,8 +23,14 @@ import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsBucketAvg extends BaseAggParams { + customMetric?: AggConfigSerialized; + customBucket?: AggConfigSerialized; +} + export interface BucketAvgMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.test.ts new file mode 100644 index 0000000000000..7e08bc9954510 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.test.ts @@ -0,0 +1,78 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggBucketAvg } from './bucket_avg_fn'; + +describe('agg_expression_functions', () => { + describe('aggBucketAvg', () => { + const fn = functionWrapper(aggBucketAvg()); + + test('handles customMetric and customBucket as a subexpression', () => { + const actual = fn({ + customMetric: fn({}), + customBucket: fn({}), + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "customBucket": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "avg_bucket", + }, + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "avg_bucket", + }, + "json": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.ts b/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.ts new file mode 100644 index 0000000000000..56643a2df54bd --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_avg_fn.ts @@ -0,0 +1,107 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggBucketAvg'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign< + AggArgs, + { customBucket?: AggExpressionType; customMetric?: AggExpressionType } +>; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggBucketAvg = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.bucket_avg.help', { + defaultMessage: 'Generates a serialized agg config for a Avg Bucket agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.bucket_avg.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + customBucket: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.customBucket.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.customMetric.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_avg.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.AVG_BUCKET, + params: { + ...rest, + customBucket: args.customBucket?.value, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts index 1e57a2dd8e38e..dde328008b88a 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_max.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_max.ts @@ -22,8 +22,14 @@ import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsBucketMax extends BaseAggParams { + customMetric?: AggConfigSerialized; + customBucket?: AggConfigSerialized; +} + export interface BucketMaxMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.test.ts new file mode 100644 index 0000000000000..b789bdf51ebd5 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.test.ts @@ -0,0 +1,78 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggBucketMax } from './bucket_max_fn'; + +describe('agg_expression_functions', () => { + describe('aggBucketMax', () => { + const fn = functionWrapper(aggBucketMax()); + + test('handles customMetric and customBucket as a subexpression', () => { + const actual = fn({ + customMetric: fn({}), + customBucket: fn({}), + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "customBucket": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "max_bucket", + }, + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "max_bucket", + }, + "json": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.ts b/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.ts new file mode 100644 index 0000000000000..896e9cf839605 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_max_fn.ts @@ -0,0 +1,107 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggBucketMax'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign< + AggArgs, + { customBucket?: AggExpressionType; customMetric?: AggExpressionType } +>; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggBucketMax = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.bucket_max.help', { + defaultMessage: 'Generates a serialized agg config for a Max Bucket agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.bucket_max.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + customBucket: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.customBucket.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.customMetric.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_max.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MAX_BUCKET, + params: { + ...rest, + customBucket: args.customBucket?.value, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts index 0484af23a7141..9949524ce6110 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_min.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_min.ts @@ -22,8 +22,14 @@ import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsBucketMin extends BaseAggParams { + customMetric?: AggConfigSerialized; + customBucket?: AggConfigSerialized; +} + export interface BucketMinMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.test.ts new file mode 100644 index 0000000000000..6ebc83417813b --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.test.ts @@ -0,0 +1,78 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggBucketMin } from './bucket_min_fn'; + +describe('agg_expression_functions', () => { + describe('aggBucketMin', () => { + const fn = functionWrapper(aggBucketMin()); + + test('handles customMetric and customBucket as a subexpression', () => { + const actual = fn({ + customMetric: fn({}), + customBucket: fn({}), + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "customBucket": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "min_bucket", + }, + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "min_bucket", + }, + "json": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.ts b/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.ts new file mode 100644 index 0000000000000..2ae3d9211227a --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_min_fn.ts @@ -0,0 +1,107 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggBucketMin'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign< + AggArgs, + { customBucket?: AggExpressionType; customMetric?: AggExpressionType } +>; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggBucketMin = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.bucket_min.help', { + defaultMessage: 'Generates a serialized agg config for a Min Bucket agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.bucket_min.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + customBucket: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.customBucket.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.customMetric.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_min.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MIN_BUCKET, + params: { + ...rest, + customBucket: args.customBucket?.value, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts index 0a4d29a18a980..e69ae5798c6e1 100644 --- a/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/bucket_sum.ts @@ -22,8 +22,14 @@ import { MetricAggType } from './metric_agg_type'; import { makeNestedLabel } from './lib/make_nested_label'; import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsBucketSum extends BaseAggParams { + customMetric?: AggConfigSerialized; + customBucket?: AggConfigSerialized; +} + export interface BucketSumMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.test.ts new file mode 100644 index 0000000000000..71549f41b1d15 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.test.ts @@ -0,0 +1,78 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggBucketSum } from './bucket_sum_fn'; + +describe('agg_expression_functions', () => { + describe('aggBucketSum', () => { + const fn = functionWrapper(aggBucketSum()); + + test('handles customMetric and customBucket as a subexpression', () => { + const actual = fn({ + customMetric: fn({}), + customBucket: fn({}), + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "customBucket": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "sum_bucket", + }, + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customBucket": undefined, + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "sum_bucket", + }, + "json": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.ts b/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.ts new file mode 100644 index 0000000000000..eceb11a90f293 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/bucket_sum_fn.ts @@ -0,0 +1,107 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggBucketSum'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign< + AggArgs, + { customBucket?: AggExpressionType; customMetric?: AggExpressionType } +>; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggBucketSum = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.bucket_sum.help', { + defaultMessage: 'Generates a serialized agg config for a Sum Bucket agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.bucket_sum.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + customBucket: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.customBucket.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.customMetric.help', { + defaultMessage: 'Agg config to use for building sibling pipeline aggregations', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.bucket_sum.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.SUM_BUCKET, + params: { + ...rest, + customBucket: args.customBucket?.value, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/cardinality.ts b/src/plugins/data/public/search/aggs/metrics/cardinality.ts index 10b6b5aff1abd..af594195fe027 100644 --- a/src/plugins/data/public/search/aggs/metrics/cardinality.ts +++ b/src/plugins/data/public/search/aggs/metrics/cardinality.ts @@ -22,11 +22,16 @@ import { MetricAggType, IMetricAggConfig } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const uniqueCountTitle = i18n.translate('data.search.aggs.metrics.uniqueCountTitle', { defaultMessage: 'Unique Count', }); +export interface AggParamsCardinality extends BaseAggParams { + field: string; +} + export interface CardinalityMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/cardinality_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/cardinality_fn.test.ts new file mode 100644 index 0000000000000..4008819018ee5 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/cardinality_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggCardinality } from './cardinality_fn'; + +describe('agg_expression_functions', () => { + describe('aggCardinality', () => { + const fn = functionWrapper(aggCardinality()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "cardinality", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/cardinality_fn.ts b/src/plugins/data/public/search/aggs/metrics/cardinality_fn.ts new file mode 100644 index 0000000000000..f30429993638f --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/cardinality_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggCardinality'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggCardinality = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.cardinality.help', { + defaultMessage: 'Generates a serialized agg config for a Cardinality agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cardinality.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.cardinality.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cardinality.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.cardinality.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cardinality.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cardinality.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.CARDINALITY, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/count_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/count_fn.test.ts new file mode 100644 index 0000000000000..846feb9296fca --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/count_fn.test.ts @@ -0,0 +1,59 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggCount } from './count_fn'; + +describe('agg_expression_functions', () => { + describe('aggCount', () => { + const fn = functionWrapper(aggCount()); + + test('correctly creates agg type', () => { + const actual = fn({}); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "json": undefined, + }, + "schema": undefined, + "type": "count", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/count_fn.ts b/src/plugins/data/public/search/aggs/metrics/count_fn.ts new file mode 100644 index 0000000000000..f4c7e8e854230 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/count_fn.ts @@ -0,0 +1,88 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggCount'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggCount = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.count.help', { + defaultMessage: 'Generates a serialized agg config for a Count agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.count.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.count.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.count.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.count.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.count.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.COUNT, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts index 8ca922e144a1f..67e907239799a 100644 --- a/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/cumulative_sum.ts @@ -22,8 +22,15 @@ import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsCumulativeSum extends BaseAggParams { + buckets_path: string; + customMetric?: AggConfigSerialized; + metricAgg?: string; +} + export interface CumulativeSumMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.test.ts new file mode 100644 index 0000000000000..3cf53e3da153e --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggCumulativeSum } from './cumulative_sum_fn'; + +describe('agg_expression_functions', () => { + describe('aggCumulativeSum', () => { + const fn = functionWrapper(aggCumulativeSum()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "cumulative_sum", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + metricAgg: 'sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": "sum", + }, + "schema": undefined, + "type": "cumulative_sum", + }, + } + `); + }); + + test('handles customMetric as a subexpression', () => { + const actual = fn({ + customMetric: fn({ buckets_path: 'the_sum' }), + buckets_path: 'the_sum', + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "cumulative_sum", + }, + "json": undefined, + "metricAgg": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + buckets_path: 'the_sum', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + buckets_path: 'the_sum', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.ts b/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.ts new file mode 100644 index 0000000000000..950df03b10134 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/cumulative_sum_fn.ts @@ -0,0 +1,111 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggCumulativeSum'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggCumulativeSum = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.cumulative_sum.help', { + defaultMessage: 'Generates a serialized agg config for a Cumulative Sum agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + metricAgg: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.metricAgg.help', { + defaultMessage: + 'Id for finding agg config to use for building parent pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.customMetric.help', { + defaultMessage: 'Agg config to use for building parent pipeline aggregations', + }), + }, + buckets_path: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.buckets_path.help', { + defaultMessage: 'Path to the metric of interest', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.cumulative_sum.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.CUMULATIVE_SUM, + params: { + ...rest, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/derivative.ts b/src/plugins/data/public/search/aggs/metrics/derivative.ts index 5752a72c846aa..edb907ca4ed41 100644 --- a/src/plugins/data/public/search/aggs/metrics/derivative.ts +++ b/src/plugins/data/public/search/aggs/metrics/derivative.ts @@ -22,8 +22,15 @@ import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsDerivative extends BaseAggParams { + buckets_path: string; + customMetric?: AggConfigSerialized; + metricAgg?: string; +} + export interface DerivativeMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/derivative_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/derivative_fn.test.ts new file mode 100644 index 0000000000000..79ea7292104ee --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/derivative_fn.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggDerivative } from './derivative_fn'; + +describe('agg_expression_functions', () => { + describe('aggDerivative', () => { + const fn = functionWrapper(aggDerivative()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "derivative", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + metricAgg: 'sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": "sum", + }, + "schema": undefined, + "type": "derivative", + }, + } + `); + }); + + test('handles customMetric as a subexpression', () => { + const actual = fn({ + customMetric: fn({ buckets_path: 'the_sum' }), + buckets_path: 'the_sum', + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "derivative", + }, + "json": undefined, + "metricAgg": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + buckets_path: 'the_sum', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + buckets_path: 'the_sum', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/derivative_fn.ts b/src/plugins/data/public/search/aggs/metrics/derivative_fn.ts new file mode 100644 index 0000000000000..90b88b4de2712 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/derivative_fn.ts @@ -0,0 +1,111 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggDerivative'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggDerivative = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.derivative.help', { + defaultMessage: 'Generates a serialized agg config for a Derivative agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.derivative.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.derivative.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.derivative.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + metricAgg: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.derivative.metricAgg.help', { + defaultMessage: + 'Id for finding agg config to use for building parent pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.derivative.customMetric.help', { + defaultMessage: 'Agg config to use for building parent pipeline aggregations', + }), + }, + buckets_path: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.derivative.buckets_path.help', { + defaultMessage: 'Path to the metric of interest', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.derivative.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.derivative.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.DERIVATIVE, + params: { + ...rest, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/geo_bounds.ts b/src/plugins/data/public/search/aggs/metrics/geo_bounds.ts index 00927ebba56bf..864e97ca8dfe7 100644 --- a/src/plugins/data/public/search/aggs/metrics/geo_bounds.ts +++ b/src/plugins/data/public/search/aggs/metrics/geo_bounds.ts @@ -22,6 +22,11 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsGeoBounds extends BaseAggParams { + field: string; +} export interface GeoBoundsMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; diff --git a/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.test.ts new file mode 100644 index 0000000000000..96bd31916784a --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggGeoBounds } from './geo_bounds_fn'; + +describe('agg_expression_functions', () => { + describe('aggGeoBounds', () => { + const fn = functionWrapper(aggGeoBounds()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "geo_bounds", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.ts b/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.ts new file mode 100644 index 0000000000000..8ba71a098fc70 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/geo_bounds_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggGeoBounds'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggGeoBounds = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.geo_bounds.help', { + defaultMessage: 'Generates a serialized agg config for a Geo Bounds agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_bounds.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.geo_bounds.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_bounds.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.geo_bounds.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_bounds.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_bounds.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.GEO_BOUNDS, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/geo_centroid.ts b/src/plugins/data/public/search/aggs/metrics/geo_centroid.ts index a4b084f794a5d..2bbb6b2de8d87 100644 --- a/src/plugins/data/public/search/aggs/metrics/geo_centroid.ts +++ b/src/plugins/data/public/search/aggs/metrics/geo_centroid.ts @@ -22,6 +22,11 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsGeoCentroid extends BaseAggParams { + field: string; +} export interface GeoCentroidMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; diff --git a/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.test.ts new file mode 100644 index 0000000000000..bf9a4548bafbf --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggGeoCentroid } from './geo_centroid_fn'; + +describe('agg_expression_functions', () => { + describe('aggGeoCentroid', () => { + const fn = functionWrapper(aggGeoCentroid()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "geo_centroid", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.ts b/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.ts new file mode 100644 index 0000000000000..464f9b535cd8b --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/geo_centroid_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggGeoCentroid'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggGeoCentroid = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.geo_centroid.help', { + defaultMessage: 'Generates a serialized agg config for a Geo Centroid agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_centroid.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.geo_centroid.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_centroid.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.geo_centroid.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_centroid.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.geo_centroid.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.GEO_CENTROID, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/index.ts b/src/plugins/data/public/search/aggs/metrics/index.ts index eb93e99427f65..ef7de68b05de9 100644 --- a/src/plugins/data/public/search/aggs/metrics/index.ts +++ b/src/plugins/data/public/search/aggs/metrics/index.ts @@ -21,3 +21,23 @@ export * from './metric_agg_type'; export * from './metric_agg_types'; export * from './lib/parent_pipeline_agg_helper'; export * from './lib/sibling_pipeline_agg_helper'; +export { AggParamsAvg } from './avg'; +export { AggParamsCardinality } from './cardinality'; +export { AggParamsGeoBounds } from './geo_bounds'; +export { AggParamsGeoCentroid } from './geo_centroid'; +export { AggParamsMax } from './max'; +export { AggParamsMedian } from './median'; +export { AggParamsMin } from './min'; +export { AggParamsStdDeviation } from './std_deviation'; +export { AggParamsSum } from './sum'; +export { AggParamsBucketAvg } from './bucket_avg'; +export { AggParamsBucketMax } from './bucket_max'; +export { AggParamsBucketMin } from './bucket_min'; +export { AggParamsBucketSum } from './bucket_sum'; +export { AggParamsCumulativeSum } from './cumulative_sum'; +export { AggParamsDerivative } from './derivative'; +export { AggParamsMovingAvg } from './moving_avg'; +export { AggParamsPercentileRanks } from './percentile_ranks'; +export { AggParamsPercentiles } from './percentiles'; +export { AggParamsSerialDiff } from './serial_diff'; +export { AggParamsTopHit } from './top_hit'; diff --git a/src/plugins/data/public/search/aggs/metrics/max.ts b/src/plugins/data/public/search/aggs/metrics/max.ts index 88e8b485cb73f..49cbfba5a269d 100644 --- a/src/plugins/data/public/search/aggs/metrics/max.ts +++ b/src/plugins/data/public/search/aggs/metrics/max.ts @@ -22,11 +22,16 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const maxTitle = i18n.translate('data.search.aggs.metrics.maxTitle', { defaultMessage: 'Max', }); +export interface AggParamsMax extends BaseAggParams { + field: string; +} + export interface MaxMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/max_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/max_fn.test.ts new file mode 100644 index 0000000000000..156b51ca54af5 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/max_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggMax } from './max_fn'; + +describe('agg_expression_functions', () => { + describe('aggMax', () => { + const fn = functionWrapper(aggMax()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "max", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/max_fn.ts b/src/plugins/data/public/search/aggs/metrics/max_fn.ts new file mode 100644 index 0000000000000..1d68c8919fca8 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/max_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggMax'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggMax = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.max.help', { + defaultMessage: 'Generates a serialized agg config for a Max agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.max.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.max.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.max.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.max.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.max.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.max.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MAX, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/median.ts b/src/plugins/data/public/search/aggs/metrics/median.ts index a398f017602b0..725fdcb2400d1 100644 --- a/src/plugins/data/public/search/aggs/metrics/median.ts +++ b/src/plugins/data/public/search/aggs/metrics/median.ts @@ -22,11 +22,16 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const medianTitle = i18n.translate('data.search.aggs.metrics.medianTitle', { defaultMessage: 'Median', }); +export interface AggParamsMedian extends BaseAggParams { + field: string; +} + export interface MedianMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/median_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/median_fn.test.ts new file mode 100644 index 0000000000000..69200c35426c8 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/median_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggMedian } from './median_fn'; + +describe('agg_expression_functions', () => { + describe('aggMedian', () => { + const fn = functionWrapper(aggMedian()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "median", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/median_fn.ts b/src/plugins/data/public/search/aggs/metrics/median_fn.ts new file mode 100644 index 0000000000000..2e8e89992136e --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/median_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggMedian'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggMedian = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.median.help', { + defaultMessage: 'Generates a serialized agg config for a Median agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.median.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.median.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.median.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.median.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.median.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.median.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MEDIAN, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/min.ts b/src/plugins/data/public/search/aggs/metrics/min.ts index aae16f357186c..0f52aa8a4f788 100644 --- a/src/plugins/data/public/search/aggs/metrics/min.ts +++ b/src/plugins/data/public/search/aggs/metrics/min.ts @@ -22,11 +22,16 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const minTitle = i18n.translate('data.search.aggs.metrics.minTitle', { defaultMessage: 'Min', }); +export interface AggParamsMin extends BaseAggParams { + field: string; +} + export interface MinMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/min_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/min_fn.test.ts new file mode 100644 index 0000000000000..ef32d086e41f7 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/min_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggMin } from './min_fn'; + +describe('agg_expression_functions', () => { + describe('aggMin', () => { + const fn = functionWrapper(aggMin()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "min", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/min_fn.ts b/src/plugins/data/public/search/aggs/metrics/min_fn.ts new file mode 100644 index 0000000000000..b51da46a137b0 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/min_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggMin'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggMin = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.min.help', { + defaultMessage: 'Generates a serialized agg config for a Min agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.min.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.min.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.min.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.min.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.min.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.min.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MIN, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts index 94b9b1d8cd487..38a824629d304 100644 --- a/src/plugins/data/public/search/aggs/metrics/moving_avg.ts +++ b/src/plugins/data/public/search/aggs/metrics/moving_avg.ts @@ -22,8 +22,17 @@ import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsMovingAvg extends BaseAggParams { + buckets_path: string; + window?: number; + script?: string; + customMetric?: AggConfigSerialized; + metricAgg?: string; +} + export interface MovingAvgMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.test.ts new file mode 100644 index 0000000000000..d6c0e6b2cbd6e --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.test.ts @@ -0,0 +1,130 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggMovingAvg } from './moving_avg_fn'; + +describe('agg_expression_functions', () => { + describe('aggMovingAvg', () => { + const fn = functionWrapper(aggMovingAvg()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + "script": undefined, + "window": undefined, + }, + "schema": undefined, + "type": "moving_avg", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + metricAgg: 'sum', + window: 10, + script: 'test', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": "sum", + "script": "test", + "window": 10, + }, + "schema": undefined, + "type": "moving_avg", + }, + } + `); + }); + + test('handles customMetric as a subexpression', () => { + const actual = fn({ + customMetric: fn({ buckets_path: 'the_sum' }), + buckets_path: 'the_sum', + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + "script": undefined, + "window": undefined, + }, + "schema": undefined, + "type": "moving_avg", + }, + "json": undefined, + "metricAgg": undefined, + "script": undefined, + "window": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + buckets_path: 'the_sum', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + buckets_path: 'the_sum', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.ts b/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.ts new file mode 100644 index 0000000000000..54a3fa176385b --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/moving_avg_fn.ts @@ -0,0 +1,124 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggMovingAvg'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggMovingAvg = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.moving_avg.help', { + defaultMessage: 'Generates a serialized agg config for a Moving Average agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.moving_avg.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + metricAgg: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.metricAgg.help', { + defaultMessage: + 'Id for finding agg config to use for building parent pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.customMetric.help', { + defaultMessage: 'Agg config to use for building parent pipeline aggregations', + }), + }, + window: { + types: ['number'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.window.help', { + defaultMessage: 'The size of window to "slide" across the histogram.', + }), + }, + buckets_path: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.derivative.buckets_path.help', { + defaultMessage: 'Path to the metric of interest', + }), + }, + script: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.script.help', { + defaultMessage: + 'Id for finding agg config to use for building parent pipeline aggregations', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.moving_avg.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.MOVING_FN, + params: { + ...rest, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts index 0d79665ff9c4e..c8383f6bcc3d9 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks.ts @@ -24,6 +24,12 @@ import { getPercentileValue } from './percentiles_get_value'; import { METRIC_TYPES } from './metric_agg_types'; import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsPercentileRanks extends BaseAggParams { + field: string; + values?: number[]; +} // required by the values editor export type IPercentileRanksAggConfig = IResponseAggConfig; diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.test.ts new file mode 100644 index 0000000000000..e3ce91bafd40a --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.test.ts @@ -0,0 +1,93 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggPercentileRanks } from './percentile_ranks_fn'; + +describe('agg_expression_functions', () => { + describe('aggPercentileRanks', () => { + const fn = functionWrapper(aggPercentileRanks()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "values": undefined, + }, + "schema": undefined, + "type": "percentile_ranks", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + values: [1, 2, 3], + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "values": Array [ + 1, + 2, + 3, + ], + }, + "schema": undefined, + "type": "percentile_ranks", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.ts b/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.ts new file mode 100644 index 0000000000000..851e938f28c1c --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/percentile_ranks_fn.ts @@ -0,0 +1,102 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggPercentileRanks'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggPercentileRanks = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.percentile_ranks.help', { + defaultMessage: 'Generates a serialized agg config for a Percentile Ranks agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + values: { + types: ['number'], + multi: true, + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.values.help', { + defaultMessage: 'Range of percentiles ranks', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentile_ranks.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.PERCENTILE_RANKS, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles.ts b/src/plugins/data/public/search/aggs/metrics/percentiles.ts index 040a52588dd94..ad3c19cfaffcc 100644 --- a/src/plugins/data/public/search/aggs/metrics/percentiles.ts +++ b/src/plugins/data/public/search/aggs/metrics/percentiles.ts @@ -25,6 +25,12 @@ import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_respons import { getPercentileValue } from './percentiles_get_value'; import { ordinalSuffix } from './lib/ordinal_suffix'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsPercentiles extends BaseAggParams { + field: string; + percents?: number[]; +} export type IPercentileAggConfig = IResponseAggConfig; diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/percentiles_fn.test.ts new file mode 100644 index 0000000000000..2074cc1d89527 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/percentiles_fn.test.ts @@ -0,0 +1,93 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggPercentiles } from './percentiles_fn'; + +describe('agg_expression_functions', () => { + describe('aggPercentiles', () => { + const fn = functionWrapper(aggPercentiles()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "percents": undefined, + }, + "schema": undefined, + "type": "percentiles", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + percents: [1, 2, 3], + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "percents": Array [ + 1, + 2, + 3, + ], + }, + "schema": undefined, + "type": "percentiles", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/percentiles_fn.ts b/src/plugins/data/public/search/aggs/metrics/percentiles_fn.ts new file mode 100644 index 0000000000000..b799be07925fa --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/percentiles_fn.ts @@ -0,0 +1,102 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggPercentiles'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggPercentiles = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.percentiles.help', { + defaultMessage: 'Generates a serialized agg config for a Percentiles agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentiles.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.percentiles.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentiles.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.percentiles.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + percents: { + types: ['number'], + multi: true, + help: i18n.translate('data.search.aggs.metrics.percentiles.percents.help', { + defaultMessage: 'Range of percentiles ranks', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentiles.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.percentiles.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.PERCENTILES, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts index 2b1498560f862..fe112a50ad3c1 100644 --- a/src/plugins/data/public/search/aggs/metrics/serial_diff.ts +++ b/src/plugins/data/public/search/aggs/metrics/serial_diff.ts @@ -22,8 +22,15 @@ import { MetricAggType } from './metric_agg_type'; import { parentPipelineAggHelper } from './lib/parent_pipeline_agg_helper'; import { makeNestedLabel } from './lib/make_nested_label'; import { METRIC_TYPES } from './metric_agg_types'; +import { AggConfigSerialized, BaseAggParams } from '../types'; import { GetInternalStartServicesFn } from '../../../types'; +export interface AggParamsSerialDiff extends BaseAggParams { + buckets_path: string; + customMetric?: AggConfigSerialized; + metricAgg?: string; +} + export interface SerialDiffMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.test.ts new file mode 100644 index 0000000000000..1bb859ad4bad8 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggSerialDiff } from './serial_diff_fn'; + +describe('agg_expression_functions', () => { + describe('aggSerialDiff', () => { + const fn = functionWrapper(aggSerialDiff()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "serial_diff", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + buckets_path: 'the_sum', + metricAgg: 'sum', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": "sum", + }, + "schema": undefined, + "type": "serial_diff", + }, + } + `); + }); + + test('handles customMetric as a subexpression', () => { + const actual = fn({ + customMetric: fn({ buckets_path: 'the_sum' }), + buckets_path: 'the_sum', + }); + + expect(actual.value.params).toMatchInlineSnapshot(` + Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": Object { + "enabled": true, + "id": undefined, + "params": Object { + "buckets_path": "the_sum", + "customLabel": undefined, + "customMetric": undefined, + "json": undefined, + "metricAgg": undefined, + }, + "schema": undefined, + "type": "serial_diff", + }, + "json": undefined, + "metricAgg": undefined, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + json: '{ "foo": true }', + buckets_path: 'the_sum', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + json: '/// intentionally malformed json ///', + buckets_path: 'the_sum', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.ts b/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.ts new file mode 100644 index 0000000000000..9ba313aff7386 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/serial_diff_fn.ts @@ -0,0 +1,111 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Assign } from '@kbn/utility-types'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggSerialDiff'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Arguments = Assign; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggSerialDiff = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.serial_diff.help', { + defaultMessage: 'Generates a serialized agg config for a Serial Differencing agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.serial_diff.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + metricAgg: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.metricAgg.help', { + defaultMessage: + 'Id for finding agg config to use for building parent pipeline aggregations', + }), + }, + customMetric: { + types: ['agg_type'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.customMetric.help', { + defaultMessage: 'Agg config to use for building parent pipeline aggregations', + }), + }, + buckets_path: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.serial_diff.buckets_path.help', { + defaultMessage: 'Path to the metric of interest', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.serial_diff.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.SERIAL_DIFF, + params: { + ...rest, + customMetric: args.customMetric?.value, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation.ts index e972132542ceb..1733d5476f667 100644 --- a/src/plugins/data/public/search/aggs/metrics/std_deviation.ts +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation.ts @@ -24,6 +24,11 @@ import { METRIC_TYPES } from './metric_agg_types'; import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsStdDeviation extends BaseAggParams { + field: string; +} interface ValProp { valProp: string[]; diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.test.ts new file mode 100644 index 0000000000000..bfa6aa7cc4122 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggStdDeviation } from './std_deviation_fn'; + +describe('agg_expression_functions', () => { + describe('aggStdDeviation', () => { + const fn = functionWrapper(aggStdDeviation()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "std_dev", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.ts b/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.ts new file mode 100644 index 0000000000000..70623e2e48041 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/std_deviation_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggStdDeviation'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggStdDeviation = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.std_deviation.help', { + defaultMessage: 'Generates a serialized agg config for a Standard Deviation agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.std_deviation.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.std_deviation.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.std_deviation.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.std_deviation.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.std_deviation.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.std_deviation.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.STD_DEV, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/sum.ts b/src/plugins/data/public/search/aggs/metrics/sum.ts index 545c6d6a4939e..70fc379f2d5f1 100644 --- a/src/plugins/data/public/search/aggs/metrics/sum.ts +++ b/src/plugins/data/public/search/aggs/metrics/sum.ts @@ -22,11 +22,16 @@ import { MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; const sumTitle = i18n.translate('data.search.aggs.metrics.sumTitle', { defaultMessage: 'Sum', }); +export interface AggParamsSum extends BaseAggParams { + field: string; +} + export interface SumMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; } diff --git a/src/plugins/data/public/search/aggs/metrics/sum_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/sum_fn.test.ts new file mode 100644 index 0000000000000..6e57632ba84cc --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/sum_fn.test.ts @@ -0,0 +1,64 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggSum } from './sum_fn'; + +describe('agg_expression_functions', () => { + describe('aggSum', () => { + const fn = functionWrapper(aggSum()); + + test('required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + }, + "schema": undefined, + "type": "sum", + }, + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/sum_fn.ts b/src/plugins/data/public/search/aggs/metrics/sum_fn.ts new file mode 100644 index 0000000000000..a277aef02693f --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/sum_fn.ts @@ -0,0 +1,95 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggSum'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggSum = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.sum.help', { + defaultMessage: 'Generates a serialized agg config for a Sum agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.sum.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.sum.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.sum.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.sum.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.sum.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.sum.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.SUM, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit.ts b/src/plugins/data/public/search/aggs/metrics/top_hit.ts index 15da2b485aee7..df7a76f151c07 100644 --- a/src/plugins/data/public/search/aggs/metrics/top_hit.ts +++ b/src/plugins/data/public/search/aggs/metrics/top_hit.ts @@ -23,6 +23,15 @@ import { IMetricAggConfig, MetricAggType } from './metric_agg_type'; import { METRIC_TYPES } from './metric_agg_types'; import { KBN_FIELD_TYPES } from '../../../../common'; import { GetInternalStartServicesFn } from '../../../types'; +import { BaseAggParams } from '../types'; + +export interface AggParamsTopHit extends BaseAggParams { + field: string; + aggregate: 'min' | 'max' | 'sum' | 'average' | 'concat'; + sortField?: string; + size?: number; + sortOrder?: 'desc' | 'asc'; +} export interface TopHitMetricAggDependencies { getInternalStartServices: GetInternalStartServicesFn; diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit_fn.test.ts b/src/plugins/data/public/search/aggs/metrics/top_hit_fn.test.ts new file mode 100644 index 0000000000000..d0e9788f85025 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/top_hit_fn.test.ts @@ -0,0 +1,102 @@ +/* + * 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 { functionWrapper } from '../test_helpers'; +import { aggTopHit } from './top_hit_fn'; + +describe('agg_expression_functions', () => { + describe('aggTopHit', () => { + const fn = functionWrapper(aggTopHit()); + + test('fills in defaults when only required args are provided', () => { + const actual = fn({ + field: 'machine.os.keyword', + aggregate: 'min', + }); + expect(actual).toMatchInlineSnapshot(` + Object { + "type": "agg_type", + "value": Object { + "enabled": true, + "id": undefined, + "params": Object { + "aggregate": "min", + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "size": undefined, + "sortField": undefined, + "sortOrder": undefined, + }, + "schema": undefined, + "type": "top_hits", + }, + } + `); + }); + + test('includes optional params when they are provided', () => { + const actual = fn({ + id: '1', + enabled: false, + schema: 'whatever', + field: 'machine.os.keyword', + sortOrder: 'asc', + size: 6, + aggregate: 'min', + sortField: '_score', + }); + + expect(actual.value).toMatchInlineSnapshot(` + Object { + "enabled": false, + "id": "1", + "params": Object { + "aggregate": "min", + "customLabel": undefined, + "field": "machine.os.keyword", + "json": undefined, + "size": 6, + "sortField": "_score", + "sortOrder": "asc", + }, + "schema": "whatever", + "type": "top_hits", + } + `); + }); + + test('correctly parses json string argument', () => { + const actual = fn({ + field: 'machine.os.keyword', + aggregate: 'min', + json: '{ "foo": true }', + }); + + expect(actual.value.params.json).toEqual({ foo: true }); + expect(() => { + fn({ + field: 'machine.os.keyword', + aggregate: 'min', + json: '/// intentionally malformed json ///', + }); + }).toThrowErrorMatchingInlineSnapshot(`"Unable to parse json argument string"`); + }); + }); +}); diff --git a/src/plugins/data/public/search/aggs/metrics/top_hit_fn.ts b/src/plugins/data/public/search/aggs/metrics/top_hit_fn.ts new file mode 100644 index 0000000000000..adfd22b540e06 --- /dev/null +++ b/src/plugins/data/public/search/aggs/metrics/top_hit_fn.ts @@ -0,0 +1,122 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { ExpressionFunctionDefinition } from '../../../../../expressions/public'; +import { AggExpressionType, AggExpressionFunctionArgs, METRIC_TYPES } from '../'; +import { getParsedValue } from '../utils/get_parsed_value'; + +const fnName = 'aggTopHit'; + +type Input = any; +type AggArgs = AggExpressionFunctionArgs; +type Output = AggExpressionType; +type FunctionDefinition = ExpressionFunctionDefinition; + +export const aggTopHit = (): FunctionDefinition => ({ + name: fnName, + help: i18n.translate('data.search.aggs.function.metrics.top_hit.help', { + defaultMessage: 'Generates a serialized agg config for a Top Hit agg', + }), + type: 'agg_type', + args: { + id: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.top_hit.id.help', { + defaultMessage: 'ID for this aggregation', + }), + }, + enabled: { + types: ['boolean'], + default: true, + help: i18n.translate('data.search.aggs.metrics.top_hit.enabled.help', { + defaultMessage: 'Specifies whether this aggregation should be enabled', + }), + }, + schema: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.top_hit.schema.help', { + defaultMessage: 'Schema to use for this aggregation', + }), + }, + field: { + types: ['string'], + required: true, + help: i18n.translate('data.search.aggs.metrics.top_hit.field.help', { + defaultMessage: 'Field to use for this aggregation', + }), + }, + aggregate: { + types: ['string'], + required: true, + options: ['min', 'max', 'sum', 'average', 'concat'], + help: i18n.translate('data.search.aggs.metrics.top_hit.aggregate.help', { + defaultMessage: 'Aggregate type', + }), + }, + size: { + types: ['number'], + help: i18n.translate('data.search.aggs.metrics.top_hit.size.help', { + defaultMessage: 'Max number of buckets to retrieve', + }), + }, + sortOrder: { + types: ['string'], + options: ['desc', 'asc'], + help: i18n.translate('data.search.aggs.metrics.top_hit.sortOrder.help', { + defaultMessage: 'Order in which to return the results: asc or desc', + }), + }, + sortField: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.top_hit.sortField.help', { + defaultMessage: 'Field to order results by', + }), + }, + json: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.top_hit.json.help', { + defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch', + }), + }, + customLabel: { + types: ['string'], + help: i18n.translate('data.search.aggs.metrics.top_hit.customLabel.help', { + defaultMessage: 'Represents a custom label for this aggregation', + }), + }, + }, + fn: (input, args) => { + const { id, enabled, schema, ...rest } = args; + + return { + type: 'agg_type', + value: { + id, + enabled, + schema, + type: METRIC_TYPES.TOP_HITS, + params: { + ...rest, + json: getParsedValue(args, 'json'), + }, + }, + }; + }, +}); diff --git a/src/plugins/data/public/search/aggs/types.ts b/src/plugins/data/public/search/aggs/types.ts index 8ad264f59cc27..a784bfaada4c7 100644 --- a/src/plugins/data/public/search/aggs/types.ts +++ b/src/plugins/data/public/search/aggs/types.ts @@ -30,12 +30,33 @@ import { AggParamsGeoTile, AggParamsGeoHash, AggParamsTerms, + AggParamsAvg, + AggParamsCardinality, + AggParamsGeoBounds, + AggParamsGeoCentroid, + AggParamsMax, + AggParamsMedian, + AggParamsMin, + AggParamsStdDeviation, + AggParamsSum, + AggParamsBucketAvg, + AggParamsBucketMax, + AggParamsBucketMin, + AggParamsBucketSum, + AggParamsCumulativeSum, + AggParamsDerivative, + AggParamsMovingAvg, + AggParamsPercentileRanks, + AggParamsPercentiles, + AggParamsSerialDiff, + AggParamsTopHit, AggParamsHistogram, AggParamsDateHistogram, AggTypesRegistrySetup, AggTypesRegistryStart, CreateAggConfigParams, getCalculateAutoTimeExpression, + METRIC_TYPES, BUCKET_TYPES, } from './'; @@ -102,4 +123,25 @@ export interface AggParamsMapping { [BUCKET_TYPES.HISTOGRAM]: AggParamsHistogram; [BUCKET_TYPES.DATE_HISTOGRAM]: AggParamsDateHistogram; [BUCKET_TYPES.TERMS]: AggParamsTerms; + [METRIC_TYPES.AVG]: AggParamsAvg; + [METRIC_TYPES.CARDINALITY]: AggParamsCardinality; + [METRIC_TYPES.COUNT]: BaseAggParams; + [METRIC_TYPES.GEO_BOUNDS]: AggParamsGeoBounds; + [METRIC_TYPES.GEO_CENTROID]: AggParamsGeoCentroid; + [METRIC_TYPES.MAX]: AggParamsMax; + [METRIC_TYPES.MEDIAN]: AggParamsMedian; + [METRIC_TYPES.MIN]: AggParamsMin; + [METRIC_TYPES.STD_DEV]: AggParamsStdDeviation; + [METRIC_TYPES.SUM]: AggParamsSum; + [METRIC_TYPES.AVG_BUCKET]: AggParamsBucketAvg; + [METRIC_TYPES.MAX_BUCKET]: AggParamsBucketMax; + [METRIC_TYPES.MIN_BUCKET]: AggParamsBucketMin; + [METRIC_TYPES.SUM_BUCKET]: AggParamsBucketSum; + [METRIC_TYPES.CUMULATIVE_SUM]: AggParamsCumulativeSum; + [METRIC_TYPES.DERIVATIVE]: AggParamsDerivative; + [METRIC_TYPES.MOVING_FN]: AggParamsMovingAvg; + [METRIC_TYPES.PERCENTILE_RANKS]: AggParamsPercentileRanks; + [METRIC_TYPES.PERCENTILES]: AggParamsPercentiles; + [METRIC_TYPES.SERIAL_DIFF]: AggParamsSerialDiff; + [METRIC_TYPES.TOP_HITS]: AggParamsTopHit; } From c7ae1c0e95766955bb40eb3fdb5287e1e482d944 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 5 May 2020 15:05:05 -0400 Subject: [PATCH 26/72] [Uptime] Flatten dynamic settings object, update saved object mapping (#64856) * Flatten dynamic settings object, update saved object mapping. * Update broken types. * Delete commented code. * Rename a test. --- .../common/constants/settings_defaults.ts | 6 ++--- .../common/runtime_types/dynamic_settings.ts | 9 ++----- .../alerts/alerts_containers/alert_tls.tsx | 4 +-- .../certificate_form.test.tsx.snap | 6 ++--- .../__snapshots__/indices_form.test.tsx.snap | 6 ++--- .../__tests__/certificate_form.test.tsx | 3 ++- .../settings/__tests__/indices_form.test.tsx | 3 ++- .../components/settings/certificate_form.tsx | 25 ++++++------------- .../uptime/public/hooks/use_cert_status.ts | 4 +-- .../plugins/uptime/public/pages/settings.tsx | 14 ++++------- .../lib/alerts/__tests__/status_check.test.ts | 12 +++------ .../plugins/uptime/server/lib/alerts/tls.ts | 14 +++++------ .../lib/requests/__tests__/get_certs.test.ts | 3 ++- .../uptime/server/lib/saved_objects.ts | 14 ++++------- .../apis/uptime/rest/dynamic_settings.ts | 13 +++++----- .../test/functional/apps/uptime/settings.ts | 20 +++++++-------- .../functional/services/uptime/settings.ts | 6 ++--- 17 files changed, 65 insertions(+), 97 deletions(-) diff --git a/x-pack/plugins/uptime/common/constants/settings_defaults.ts b/x-pack/plugins/uptime/common/constants/settings_defaults.ts index b7986679a09ca..82575e875577b 100644 --- a/x-pack/plugins/uptime/common/constants/settings_defaults.ts +++ b/x-pack/plugins/uptime/common/constants/settings_defaults.ts @@ -8,8 +8,6 @@ import { DynamicSettings } from '../runtime_types'; export const DYNAMIC_SETTINGS_DEFAULTS: DynamicSettings = { heartbeatIndices: 'heartbeat-8*', - certThresholds: { - expiration: 30, - age: 365, - }, + certAgeThreshold: 365, + certExpirationThreshold: 30, }; diff --git a/x-pack/plugins/uptime/common/runtime_types/dynamic_settings.ts b/x-pack/plugins/uptime/common/runtime_types/dynamic_settings.ts index da887cc5055c1..a0ec92f7d869b 100644 --- a/x-pack/plugins/uptime/common/runtime_types/dynamic_settings.ts +++ b/x-pack/plugins/uptime/common/runtime_types/dynamic_settings.ts @@ -6,14 +6,10 @@ import * as t from 'io-ts'; -export const CertStateThresholdsType = t.type({ - age: t.number, - expiration: t.number, -}); - export const DynamicSettingsType = t.type({ heartbeatIndices: t.string, - certThresholds: CertStateThresholdsType, + certAgeThreshold: t.number, + certExpirationThreshold: t.number, }); export const DynamicSettingsSaveType = t.intersection([ @@ -27,4 +23,3 @@ export const DynamicSettingsSaveType = t.intersection([ export type DynamicSettings = t.TypeOf; export type DynamicSettingsSaveResponse = t.TypeOf; -export type CertStateThresholds = t.TypeOf; diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_tls.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_tls.tsx index ab24d0fb5ee67..a2e1c1d43526c 100644 --- a/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_tls.tsx +++ b/x-pack/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_tls.tsx @@ -18,8 +18,8 @@ export const AlertTls = () => { const { settings } = useSelector(selectDynamicSettings); return ( ); diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap index 96d472c91680d..36351da6f14c9 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/certificate_form.test.tsx.snap @@ -55,10 +55,8 @@ exports[`CertificateForm shallow renders expected elements for valid props 1`] = fieldErrors={null} formFields={ Object { - "certThresholds": Object { - "age": 36, - "expiration": 7, - }, + "certAgeThreshold": 36, + "certExpirationThreshold": 7, "heartbeatIndices": "heartbeat-8*", } } diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap index 3b0c6d99fd9f8..c5d077007e650 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/__snapshots__/indices_form.test.tsx.snap @@ -55,10 +55,8 @@ exports[`CertificateForm shallow renders expected elements for valid props 1`] = fieldErrors={null} formFields={ Object { - "certThresholds": Object { - "age": 36, - "expiration": 7, - }, + "certAgeThreshold": 36, + "certExpirationThreshold": 7, "heartbeatIndices": "heartbeat-8*", } } diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/certificate_form.test.tsx b/x-pack/plugins/uptime/public/components/settings/__tests__/certificate_form.test.tsx index 3d4bd58aabe0f..8e2348a60ddab 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/certificate_form.test.tsx +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/certificate_form.test.tsx @@ -17,7 +17,8 @@ describe('CertificateForm', () => { onChange={jest.fn()} formFields={{ heartbeatIndices: 'heartbeat-8*', - certThresholds: { expiration: 7, age: 36 }, + certExpirationThreshold: 7, + certAgeThreshold: 36, }} fieldErrors={null} isDisabled={false} diff --git a/x-pack/plugins/uptime/public/components/settings/__tests__/indices_form.test.tsx b/x-pack/plugins/uptime/public/components/settings/__tests__/indices_form.test.tsx index 07a3bf81e39d8..68a0d96d491b6 100644 --- a/x-pack/plugins/uptime/public/components/settings/__tests__/indices_form.test.tsx +++ b/x-pack/plugins/uptime/public/components/settings/__tests__/indices_form.test.tsx @@ -17,7 +17,8 @@ describe('CertificateForm', () => { onChange={jest.fn()} formFields={{ heartbeatIndices: 'heartbeat-8*', - certThresholds: { expiration: 7, age: 36 }, + certAgeThreshold: 36, + certExpirationThreshold: 7, }} fieldErrors={null} isDisabled={false} diff --git a/x-pack/plugins/uptime/public/components/settings/certificate_form.tsx b/x-pack/plugins/uptime/public/components/settings/certificate_form.tsx index 209e38785e165..06ce6b3599782 100644 --- a/x-pack/plugins/uptime/public/components/settings/certificate_form.tsx +++ b/x-pack/plugins/uptime/public/components/settings/certificate_form.tsx @@ -17,16 +17,11 @@ import { EuiFlexGroup, EuiFlexItem, } from '@elastic/eui'; -import { CertStateThresholds } from '../../../common/runtime_types'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../common/constants'; +import { DynamicSettings } from '../../../common/runtime_types'; import { SettingsFormProps } from '../../pages/settings'; -interface ChangedValues { - heartbeatIndices?: string; - certThresholds?: Partial; -} - -export type OnFieldChangeType = (changedValues: ChangedValues) => void; +export type OnFieldChangeType = (changedValues: Partial) => void; export const CertificateExpirationForm: React.FC = ({ loading, @@ -70,9 +65,7 @@ export const CertificateExpirationForm: React.FC = ({ id="xpack.uptime.sourceConfiguration.expirationThresholdDefaultValue" defaultMessage="The default value is {defaultValue}" values={{ - defaultValue: ( - {DYNAMIC_SETTINGS_DEFAULTS.certThresholds.expiration} - ), + defaultValue: {DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold}, }} /> } @@ -91,12 +84,10 @@ export const CertificateExpirationForm: React.FC = ({ fullWidth disabled={isDisabled} isLoading={loading} - value={formFields?.certThresholds?.expiration || ''} + value={formFields?.certExpirationThreshold ?? ''} onChange={e => onChange({ - certThresholds: { - expiration: Number(e.target.value), - }, + certExpirationThreshold: Number(e.target.value), }) } /> @@ -120,7 +111,7 @@ export const CertificateExpirationForm: React.FC = ({ id="xpack.uptime.sourceConfiguration.ageThresholdDefaultValue" defaultMessage="The default value is {defaultValue}" values={{ - defaultValue: {DYNAMIC_SETTINGS_DEFAULTS.certThresholds.age}, + defaultValue: {DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold}, }} /> } @@ -139,10 +130,10 @@ export const CertificateExpirationForm: React.FC = ({ fullWidth disabled={isDisabled} isLoading={loading} - value={formFields?.certThresholds?.age || ''} + value={formFields?.certAgeThreshold ?? ''} onChange={e => onChange({ - certThresholds: { age: Number(e.currentTarget.value) }, + certAgeThreshold: Number(e.currentTarget.value), }) } /> diff --git a/x-pack/plugins/uptime/public/hooks/use_cert_status.ts b/x-pack/plugins/uptime/public/hooks/use_cert_status.ts index cb54b05af9dd1..20c09e8fcc8d1 100644 --- a/x-pack/plugins/uptime/public/hooks/use_cert_status.ts +++ b/x-pack/plugins/uptime/public/hooks/use_cert_status.ts @@ -12,9 +12,9 @@ import { CERT_STATUS } from '../../common/constants'; export const useCertStatus = (expiryDate?: string, issueDate?: string) => { const dss = useSelector(selectDynamicSettings); - const expiryThreshold = dss.settings?.certThresholds?.expiration; + const expiryThreshold = dss.settings?.certExpirationThreshold; - const ageThreshold = dss.settings?.certThresholds?.age; + const ageThreshold = dss.settings?.certAgeThreshold; const certValidityDate = new Date(expiryDate ?? ''); diff --git a/x-pack/plugins/uptime/public/pages/settings.tsx b/x-pack/plugins/uptime/public/pages/settings.tsx index 52096a49435d7..7ed9cf4444343 100644 --- a/x-pack/plugins/uptime/public/pages/settings.tsx +++ b/x-pack/plugins/uptime/public/pages/settings.tsx @@ -52,10 +52,10 @@ export interface SettingsFormProps { const getFieldErrors = (formFields: DynamicSettings | null): SettingsPageFieldErrors | null => { if (formFields) { const blankStr = 'May not be blank'; - const { certThresholds: certificatesThresholds, heartbeatIndices } = formFields; + const { certAgeThreshold, certExpirationThreshold, heartbeatIndices } = formFields; const heartbeatIndErr = heartbeatIndices.match(/^\S+$/) ? '' : blankStr; - const expirationThresholdError = certificatesThresholds?.expiration ? null : blankStr; - const ageThresholdError = certificatesThresholds?.age ? null : blankStr; + const expirationThresholdError = certExpirationThreshold ? null : blankStr; + const ageThresholdError = certAgeThreshold ? null : blankStr; return { heartbeatIndices: heartbeatIndErr, certificatesThresholds: @@ -98,12 +98,8 @@ export const SettingsPage = () => { const onChangeFormField: OnFieldChangeType = changedField => { if (formFields) { setFormFields({ - heartbeatIndices: changedField.heartbeatIndices ?? formFields.heartbeatIndices, - certThresholds: Object.assign( - {}, - formFields.certThresholds, - changedField?.certThresholds ?? null - ), + ...formFields, + ...changedField, }); } }; diff --git a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts index 1cc0f1da820c1..a89e5ff62319d 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/__tests__/status_check.test.ts @@ -87,10 +87,8 @@ describe('status check alert', () => { Object { "callES": [MockFunction], "dynamicSettings": Object { - "certThresholds": Object { - "age": 365, - "expiration": 30, - }, + "certAgeThreshold": 365, + "certExpirationThreshold": 30, "heartbeatIndices": "heartbeat-8*", }, "locations": Array [], @@ -134,10 +132,8 @@ describe('status check alert', () => { Object { "callES": [MockFunction], "dynamicSettings": Object { - "certThresholds": Object { - "age": 365, - "expiration": 30, - }, + "certAgeThreshold": 365, + "certExpirationThreshold": 30, "heartbeatIndices": "heartbeat-8*", }, "locations": Array [], diff --git a/x-pack/plugins/uptime/server/lib/alerts/tls.ts b/x-pack/plugins/uptime/server/lib/alerts/tls.ts index 518e3ed93b424..5728db8bfcc8d 100644 --- a/x-pack/plugins/uptime/server/lib/alerts/tls.ts +++ b/x-pack/plugins/uptime/server/lib/alerts/tls.ts @@ -114,10 +114,10 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({ to: DEFAULT_TO, index: DEFAULT_INDEX, size: DEFAULT_SIZE, - notValidAfter: `now+${dynamicSettings.certThresholds?.expiration ?? - DYNAMIC_SETTINGS_DEFAULTS.certThresholds?.expiration}d`, - notValidBefore: `now-${dynamicSettings.certThresholds?.age ?? - DYNAMIC_SETTINGS_DEFAULTS.certThresholds?.age}d`, + notValidAfter: `now+${dynamicSettings?.certExpirationThreshold ?? + DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold}d`, + notValidBefore: `now-${dynamicSettings?.certAgeThreshold ?? + DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold}d`, sortBy: 'common_name', direction: 'desc', }); @@ -127,14 +127,14 @@ export const tlsAlertFactory: UptimeAlertTypeFactory = (_server, libs) => ({ if (foundCerts) { const absoluteExpirationThreshold = moment() .add( - dynamicSettings.certThresholds?.expiration ?? - DYNAMIC_SETTINGS_DEFAULTS.certThresholds?.expiration, + dynamicSettings.certExpirationThreshold ?? + DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold, 'd' ) .valueOf(); const absoluteAgeThreshold = moment() .subtract( - dynamicSettings.certThresholds?.age ?? DYNAMIC_SETTINGS_DEFAULTS.certThresholds?.age, + dynamicSettings.certAgeThreshold ?? DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold, 'd' ) .valueOf(); diff --git a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts index 4aec376ceadf0..689dce98859e1 100644 --- a/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts +++ b/x-pack/plugins/uptime/server/lib/requests/__tests__/get_certs.test.ts @@ -92,7 +92,8 @@ describe('getCerts', () => { callES: mockCallES, dynamicSettings: { heartbeatIndices: 'heartbeat*', - certThresholds: DYNAMIC_SETTINGS_DEFAULTS.certThresholds, + certAgeThreshold: DYNAMIC_SETTINGS_DEFAULTS.certAgeThreshold, + certExpirationThreshold: DYNAMIC_SETTINGS_DEFAULTS.certExpirationThreshold, }, index: 1, from: 'now-2d', diff --git a/x-pack/plugins/uptime/server/lib/saved_objects.ts b/x-pack/plugins/uptime/server/lib/saved_objects.ts index 28b9eaad2cf6f..5a61eb859c28b 100644 --- a/x-pack/plugins/uptime/server/lib/saved_objects.ts +++ b/x-pack/plugins/uptime/server/lib/saved_objects.ts @@ -26,15 +26,11 @@ export const umDynamicSettings: SavedObjectsType = { heartbeatIndices: { type: 'keyword', }, - certThresholds: { - properties: { - expiration: { - type: 'long', - }, - age: { - type: 'long', - }, - }, + certAgeThreshold: { + type: 'long', + }, + certExpirationThreshold: { + type: 'long', }, }, }, diff --git a/x-pack/test/api_integration/apis/uptime/rest/dynamic_settings.ts b/x-pack/test/api_integration/apis/uptime/rest/dynamic_settings.ts index 95caf50d1ca7a..e4fb1fcfe6cd0 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/dynamic_settings.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/dynamic_settings.ts @@ -7,7 +7,10 @@ import expect from '@kbn/expect'; import { isRight } from 'fp-ts/lib/Either'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { DynamicSettingsType } from '../../../../../plugins/uptime/common/runtime_types'; +import { + DynamicSettingsType, + DynamicSettings, +} from '../../../../../plugins/uptime/common/runtime_types'; import { DYNAMIC_SETTINGS_DEFAULTS } from '../../../../../plugins/uptime/common/constants'; export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); @@ -20,12 +23,10 @@ export default function({ getService }: FtrProviderContext) { }); it('can change the settings', async () => { - const newSettings = { + const newSettings: DynamicSettings = { heartbeatIndices: 'myIndex1*', - certThresholds: { - expiration: 5, - age: 15, - }, + certAgeThreshold: 15, + certExpirationThreshold: 5, }; const postResponse = await supertest .post(`/api/uptime/dynamic_settings`) diff --git a/x-pack/test/functional/apps/uptime/settings.ts b/x-pack/test/functional/apps/uptime/settings.ts index 7a813a5cdfb52..1286a9940c02c 100644 --- a/x-pack/test/functional/apps/uptime/settings.ts +++ b/x-pack/test/functional/apps/uptime/settings.ts @@ -62,10 +62,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const newFieldValues: DynamicSettings = { heartbeatIndices: 'new*', - certThresholds: { - age: 365, - expiration: 30, - }, + certAgeThreshold: 365, + certExpirationThreshold: 30, }; await settings.changeHeartbeatIndicesInput(newFieldValues.heartbeatIndices); await settings.apply(); @@ -86,8 +84,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await settings.go(); - const newErrorThreshold = '5'; - await settings.changeErrorThresholdInput(newErrorThreshold); + const newExpirationThreshold = '5'; + await settings.changeErrorThresholdInput(newExpirationThreshold); await settings.apply(); await uptimePage.goToRoot(); @@ -95,16 +93,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Verify that the settings page shows the value we previously saved await settings.go(); const fields = await settings.loadFields(); - expect(fields.certThresholds?.expiration).to.eql(newErrorThreshold); + expect(fields.certExpirationThreshold).to.eql(newExpirationThreshold); }); - it('changing certificate expiration warning threshold is reflected in settings page', async () => { + it('changing certificate expiration threshold is reflected in settings page', async () => { const settings = uptimeService.settings; await settings.go(); - const newWarningThreshold = '15'; - await settings.changeWarningThresholdInput(newWarningThreshold); + const newAgeThreshold = '15'; + await settings.changeWarningThresholdInput(newAgeThreshold); await settings.apply(); await uptimePage.goToRoot(); @@ -112,7 +110,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Verify that the settings page shows the value we previously saved await settings.go(); const fields = await settings.loadFields(); - expect(fields.certThresholds?.age).to.eql(newWarningThreshold); + expect(fields.certAgeThreshold).to.eql(newAgeThreshold); }); }); }; diff --git a/x-pack/test/functional/services/uptime/settings.ts b/x-pack/test/functional/services/uptime/settings.ts index 96f5e45ce2ca4..50c5c7093f34c 100644 --- a/x-pack/test/functional/services/uptime/settings.ts +++ b/x-pack/test/functional/services/uptime/settings.ts @@ -41,10 +41,8 @@ export function UptimeSettingsProvider({ getService }: FtrProviderContext) { return { heartbeatIndices, - certThresholds: { - age: parseInt(age, 10), - expiration: parseInt(expiration, 10), - }, + certAgeThreshold: parseInt(age, 10), + certExpirationThreshold: parseInt(expiration, 10), }; }, applyButtonIsDisabled: async () => { From fdfbf7d7f753560dc028a1dad5f65fc1fbee6679 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 5 May 2020 15:13:24 -0400 Subject: [PATCH 27/72] [Ingest pipelines] Fix bug when deleting pipeline from details panel (#65216) --- .../sections/pipelines_list/details_flyout.tsx | 5 ++++- .../application/sections/pipelines_list/main.tsx | 12 +++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx index 98243a5149c0d..0ccc097505e5d 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx @@ -73,7 +73,10 @@ export const PipelineDetailsFlyout: FunctionComponent = ({ defaultMessage: 'Delete', }), icon: , - onClick: () => onDeleteClick([pipeline.name]), + onClick: () => { + setShowPopover(false); + onDeleteClick([pipeline.name]); + }, }, ]; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx index c90ac2714a95a..0d38905c0fb49 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx @@ -125,14 +125,7 @@ export const PipelinesList: React.FunctionComponent = ({ } else { // Somehow we triggered show pipeline details, but do not have a pipeline. // We assume not found. - return ( - { - goHome(); - }} - pipelineName={pipelineNameFromLocation} - /> - ); + return ; } }; @@ -195,9 +188,10 @@ export const PipelinesList: React.FunctionComponent = ({ if (deleteResponse?.hasDeletedPipelines) { // reload pipelines list sendRequest(); + setSelectedPipeline(undefined); + goHome(); } setPipelinesToDelete([]); - setSelectedPipeline(undefined); }} pipelinesToDelete={pipelinesToDelete} /> From bec09fde87e013395a4593dd8622faf72a60b2c6 Mon Sep 17 00:00:00 2001 From: The SpaceCake Project Date: Tue, 5 May 2020 15:14:01 -0400 Subject: [PATCH 28/72] [SIEM] Add initial candidate rules for 7.8 merge may 4 (#65169) * 78 rules populated rules with a package from the siem-rules repo * Update index.ts * Update rule.ts adjust rule count to 145 Co-authored-by: Elastic Machine Co-authored-by: Garrett Spong --- .../403_response_to_a_post.json | 2 +- .../405_response_method_not_allowed.json | 2 +- ..._security_adversary_behavior_detected.json | 2 +- ...point_security_cred_dumping_prevented.json | 2 +- ...t_security_cred_manipulation_detected.json | 2 +- ..._security_cred_manipulation_prevented.json | 2 +- ...ic_endpoint_security_exploit_detected.json | 2 +- ...c_endpoint_security_exploit_prevented.json | 2 +- ...ic_endpoint_security_malware_detected.json | 2 +- ...c_endpoint_security_malware_prevented.json | 2 +- ...nt_security_permission_theft_detected.json | 2 +- ...t_security_permission_theft_prevented.json | 2 +- ...t_security_process_injection_detected.json | 2 +- ..._security_process_injection_prevented.json | 2 +- ...endpoint_security_ransomware_detected.json | 2 +- ...ndpoint_security_ransomware_prevented.json | 2 +- ...den_file_attribute_with_via_attribexe.json | 2 +- .../eql_adobe_hijack_persistence.json | 2 +- .../eql_clearing_windows_event_logs.json | 2 +- ...delete_volume_usn_journal_with_fsutil.json | 2 +- ...deleting_backup_catalogs_with_wbadmin.json | 2 +- .../eql_direct_outbound_smb_connection.json | 2 +- ...ble_windows_firewall_rules_with_netsh.json | 2 +- ...coding_or_decoding_files_via_certutil.json | 2 +- .../eql_local_scheduled_task_commands.json | 2 +- .../eql_local_service_commands.json | 2 +- ...ql_msbuild_making_network_connections.json | 2 +- .../eql_mshta_making_network_connections.json | 2 +- .../eql_psexec_lateral_movement_command.json | 2 +- ...ql_suspicious_ms_office_child_process.json | 2 +- ...l_suspicious_ms_outlook_child_process.json | 2 +- .../eql_system_shells_via_services.json | 2 +- ...usual_network_connection_via_rundll32.json | 6 +- .../eql_unusual_parentchild_relationship.json | 2 +- ...ql_unusual_process_network_connection.json | 2 +- .../eql_user_account_creation.json | 2 +- ...ume_shadow_copy_deletion_via_vssadmin.json | 2 +- ..._volume_shadow_copy_deletion_via_wmic.json | 2 +- ...l_windows_script_executing_powershell.json | 2 +- .../rules/prepackaged_rules/index.ts | 199 ++++++++++-------- .../linux_anomalous_network_activity.json | 2 +- ...linux_anomalous_network_port_activity.json | 2 +- .../linux_anomalous_network_service.json | 2 +- .../linux_anomalous_network_url_activity.json | 2 +- .../linux_anomalous_process_all_hosts.json | 2 +- .../linux_anomalous_user_name.json | 2 +- ...tempt_to_disable_iptables_or_firewall.json | 35 +++ ...nux_attempt_to_disable_syslog_service.json | 35 +++ ..._base32_encoding_or_decoding_activity.json | 53 +++++ ..._base64_encoding_or_decoding_activity.json | 53 +++++ .../linux_disable_selinux_attempt.json | 35 +++ .../linux_file_deletion_via_shred.json | 35 +++ .../linux_file_mod_writable_dir.json | 38 ++++ ...nux_hex_encoding_or_decoding_activity.json | 53 +++++ .../linux_hping_activity.json | 2 +- .../linux_iodine_activity.json | 2 +- .../linux_kernel_module_activity.json | 2 +- .../linux_kernel_module_enumeration.json | 38 ++++ .../linux_kernel_module_removal.json | 56 +++++ .../linux_mknod_activity.json | 2 +- .../linux_netcat_network_connection.json | 2 +- .../linux_nmap_activity.json | 2 +- .../linux_nping_activity.json | 2 +- .../linux_perl_tty_shell.json | 35 +++ ...nux_process_started_in_temp_directory.json | 2 +- .../linux_python_tty_shell.json | 35 +++ .../linux_setgid_bit_set_via_chmod.json | 51 +++++ .../linux_setuid_bit_set_via_chmod.json | 51 +++++ .../linux_shell_activity_by_web_server.json | 6 +- .../linux_socat_activity.json | 2 +- .../linux_strace_activity.json | 2 +- .../linux_sudoers_file_mod.json | 35 +++ .../linux_tcpdump_activity.json | 2 +- ...inux_telnet_network_activity_external.json | 38 ++++ ...inux_telnet_network_activity_internal.json | 38 ++++ .../linux_virtual_machine_fingerprinting.json | 38 ++++ .../linux_whoami_commmand.json | 2 +- .../network_dns_directly_to_the_internet.json | 2 +- ...fer_protocol_activity_to_the_internet.json | 2 +- ...hat_protocol_activity_to_the_internet.json | 2 +- .../network_nat_traversal_port_activity.json | 2 +- .../network_port_26_activity.json | 2 +- ...rk_port_8000_activity_to_the_internet.json | 2 +- ..._to_point_tunneling_protocol_activity.json | 2 +- ...k_proxy_port_activity_to_the_internet.json | 2 +- ...te_desktop_protocol_from_the_internet.json | 2 +- ...mote_desktop_protocol_to_the_internet.json | 2 +- ...mote_procedure_call_from_the_internet.json | 2 +- ...remote_procedure_call_to_the_internet.json | 2 +- ...file_sharing_activity_to_the_internet.json | 2 +- .../network_smtp_to_the_internet.json | 2 +- ..._server_port_activity_to_the_internet.json | 2 +- ...rk_ssh_secure_shell_from_the_internet.json | 2 +- ...work_ssh_secure_shell_to_the_internet.json | 2 +- .../network_telnet_port_activity.json | 2 +- .../network_tor_activity_to_the_internet.json | 2 +- ...l_network_computing_from_the_internet.json | 2 +- ...ual_network_computing_to_the_internet.json | 2 +- .../prepackaged_rules/null_user_agent.json | 2 +- .../packetbeat_dns_tunneling.json | 2 +- .../packetbeat_rare_dns_question.json | 2 +- .../packetbeat_rare_server_domain.json | 2 +- .../packetbeat_rare_urls.json | 2 +- .../packetbeat_rare_user_agent.json | 2 +- .../rare_process_by_host_linux.json | 2 +- .../rare_process_by_host_windows.json | 2 +- .../prepackaged_rules/sqlmap_user_agent.json | 2 +- .../suspicious_login_activity.json | 2 +- .../windows_anomalous_network_activity.json | 2 +- .../windows_anomalous_path_activity.json | 2 +- .../windows_anomalous_process_all_hosts.json | 2 +- .../windows_anomalous_process_creation.json | 2 +- .../windows_anomalous_script.json | 2 +- .../windows_anomalous_service.json | 2 +- .../windows_anomalous_user_name.json | 2 +- .../windows_certutil_network_connection.json | 2 +- ...and_prompt_connecting_to_the_internet.json | 2 +- ...s_command_shell_started_by_powershell.json | 2 +- ...dows_command_shell_started_by_svchost.json | 2 +- .../windows_credential_dumping_msbuild.json | 2 +- .../windows_cve_2020_0601.json | 2 +- ...ws_defense_evasion_via_filter_manager.json | 2 +- ...ecution_msbuild_started_by_office_app.json | 2 +- ...s_execution_msbuild_started_by_script.json | 2 +- ...ion_msbuild_started_by_system_process.json | 2 +- ...ows_execution_msbuild_started_renamed.json | 2 +- ...cution_msbuild_started_unusal_process.json | 2 +- ...dows_execution_via_compiled_html_file.json | 2 +- ...dows_execution_via_net_com_assemblies.json | 2 +- ...ution_via_trusted_developer_utilities.json | 2 +- ...le_program_connecting_to_the_internet.json | 2 +- .../windows_injection_msbuild.json | 2 +- ...isc_lolbin_connecting_to_the_internet.json | 2 +- .../windows_modification_of_boot_config.json | 2 +- .../windows_msxsl_network.json | 2 +- .../windows_net_command_system_account.json | 2 +- ..._persistence_via_application_shimming.json | 2 +- ...escalation_via_accessibility_features.json | 2 +- ...rocess_discovery_via_tasklist_command.json | 2 +- .../windows_rare_user_runas_event.json | 2 +- ...windows_rare_user_type10_remote_login.json | 2 +- ...er_program_connecting_to_the_internet.json | 2 +- .../windows_suspicious_pdf_reader.json | 2 +- .../windows_uac_bypass_event_viewer.json | 2 +- .../windows_whoami_command_activity.json | 2 +- 145 files changed, 999 insertions(+), 212 deletions(-) create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_iptables_or_firewall.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_syslog_service.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base16_or_base32_encoding_or_decoding_activity.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base64_encoding_or_decoding_activity.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_disable_selinux_attempt.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_deletion_via_shred.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_mod_writable_dir.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hex_encoding_or_decoding_activity.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_enumeration.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_removal.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_perl_tty_shell.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_python_tty_shell.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setgid_bit_set_via_chmod.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setuid_bit_set_via_chmod.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_sudoers_file_mod.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_external.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_internal.json create mode 100644 x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_virtual_machine_fingerprinting.json diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json index d4118d0686b11..73005db600ca0 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/403_response_to_a_post.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json index da27f0a71d281..de080ff342448 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/405_response_method_not_allowed.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json index c83c0e01d7fa0..ca97e9901975f 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_adversary_behavior_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json index 03024ad15396e..11b9fa93f5f17 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_dumping_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json index e5a128029f585..ae4b59d101a3a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json index 1c05743fae62f..2db3fbbde7547 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_cred_manipulation_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json index 3396a8563ba1c..a57d56cec9bcd 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json index 2f70c539414c6..f8f1b774a191a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_exploit_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json index cbf6c286a439f..4024a50c3a0fe 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json index 49c7c160e5daf..b21bd00229c04 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_malware_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json index e836bd037ddc5..1aba34f7b15c0 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json index e9ac8d7ba6686..b383349b5e204 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_permission_theft_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json index 8e25832b0e89a..d7f5b24548344 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json index a59428275ca22..a2595dee2f724 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_process_injection_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json index 22091d8c9b68f..9dd62717958e1 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_detected.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json index 947bfcbba39a0..cfa9ff6cca2ee 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security_ransomware_prevented.json @@ -17,4 +17,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json index 25d2232d3f6dc..b61a6236db565 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adding_the_hidden_file_attribute_with_via_attribexe.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json index 3b4d2bc040217..8d455f501d2b2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_adobe_hijack_persistence.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json index 1c73d6c276ce6..d5e60ce3c10d9 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_clearing_windows_event_logs.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json index 0bfa18398eada..6f65a871fce77 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_delete_volume_usn_journal_with_fsutil.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json index e7293eda6390f..97029cebd665a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_deleting_backup_catalogs_with_wbadmin.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json index 2896d27e19112..8bbdc72573e0d 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_direct_outbound_smb_connection.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json index 42fe51f4e0373..03af66f2cffb2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_disable_windows_firewall_rules_with_netsh.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json index eef112503da5b..aaca5242e717b 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_encoding_or_decoding_files_via_certutil.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json index dbacb2537e60f..7b674c270f884 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_scheduled_task_commands.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json index 648e83b4a5267..e842b732254ca 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_local_service_commands.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json index 5e8b260d44b55..f3d75c7fead8b 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_msbuild_making_network_connections.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json index 88bd248e258d8..eb2dd0eeff6ea 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_mshta_making_network_connections.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json index f763d2aa03363..2abf38eb1b0ef 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_psexec_lateral_movement_command.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json index 95c9c6b72f8f4..e234688a432e2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_office_child_process.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json index 7f6c9257fabfd..dcc5e5a095f12 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_suspicious_ms_outlook_child_process.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json index f1b1879fc2652..504c41f05871a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_system_shells_via_services.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json index 2a7960c939d01..c2be97f110a38 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_network_connection_via_rundll32.json @@ -5,7 +5,7 @@ ], "language": "kuery", "name": "Unusual Network Connection via RunDLL32", - "query": "process.name:rundll32.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16)", + "query": "process.name:rundll32.exe and event.action:\"Network connection detected (rule: NetworkConnect)\" and not destination.ip:(10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 or 127.0.0.0/8)", "risk_score": 21, "rule_id": "52aaab7b-b51c-441a-89ce-4387b3aea886", "severity": "low", @@ -31,5 +31,5 @@ } ], "type": "query", - "version": 2 -} \ No newline at end of file + "version": 3 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json index 9a28c87c77089..ea87ce1aea81d 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_parentchild_relationship.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json index 43a3d6f6af0b2..481768e76ee37 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_unusual_process_network_connection.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json index 7054e7f67c358..247a1cde22596 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_user_account_creation.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json index 24f1cb72504f3..700fd5215133d 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_vssadmin.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json index bad3c65024e42..59222be6c598a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_volume_shadow_copy_deletion_via_wmic.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json index 52323b169cb22..27411e35ee828 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/eql_windows_script_executing_powershell.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts index 9e185b5a5ef7c..0a2317898e8a3 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/index.ts @@ -53,88 +53,105 @@ import rule43 from './linux_anomalous_network_service.json'; import rule44 from './linux_anomalous_network_url_activity.json'; import rule45 from './linux_anomalous_process_all_hosts.json'; import rule46 from './linux_anomalous_user_name.json'; -import rule47 from './linux_hping_activity.json'; -import rule48 from './linux_iodine_activity.json'; -import rule49 from './linux_kernel_module_activity.json'; -import rule50 from './linux_mknod_activity.json'; -import rule51 from './linux_netcat_network_connection.json'; -import rule52 from './linux_nmap_activity.json'; -import rule53 from './linux_nping_activity.json'; -import rule54 from './linux_process_started_in_temp_directory.json'; -import rule55 from './linux_shell_activity_by_web_server.json'; -import rule56 from './linux_socat_activity.json'; -import rule57 from './linux_strace_activity.json'; -import rule58 from './linux_tcpdump_activity.json'; -import rule59 from './linux_whoami_commmand.json'; -import rule60 from './network_dns_directly_to_the_internet.json'; -import rule61 from './network_ftp_file_transfer_protocol_activity_to_the_internet.json'; -import rule62 from './network_irc_internet_relay_chat_protocol_activity_to_the_internet.json'; -import rule63 from './network_nat_traversal_port_activity.json'; -import rule64 from './network_port_26_activity.json'; -import rule65 from './network_port_8000_activity_to_the_internet.json'; -import rule66 from './network_pptp_point_to_point_tunneling_protocol_activity.json'; -import rule67 from './network_proxy_port_activity_to_the_internet.json'; -import rule68 from './network_rdp_remote_desktop_protocol_from_the_internet.json'; -import rule69 from './network_rdp_remote_desktop_protocol_to_the_internet.json'; -import rule70 from './network_rpc_remote_procedure_call_from_the_internet.json'; -import rule71 from './network_rpc_remote_procedure_call_to_the_internet.json'; -import rule72 from './network_smb_windows_file_sharing_activity_to_the_internet.json'; -import rule73 from './network_smtp_to_the_internet.json'; -import rule74 from './network_sql_server_port_activity_to_the_internet.json'; -import rule75 from './network_ssh_secure_shell_from_the_internet.json'; -import rule76 from './network_ssh_secure_shell_to_the_internet.json'; -import rule77 from './network_telnet_port_activity.json'; -import rule78 from './network_tor_activity_to_the_internet.json'; -import rule79 from './network_vnc_virtual_network_computing_from_the_internet.json'; -import rule80 from './network_vnc_virtual_network_computing_to_the_internet.json'; -import rule81 from './null_user_agent.json'; -import rule82 from './packetbeat_dns_tunneling.json'; -import rule83 from './packetbeat_rare_dns_question.json'; -import rule84 from './packetbeat_rare_server_domain.json'; -import rule85 from './packetbeat_rare_urls.json'; -import rule86 from './packetbeat_rare_user_agent.json'; -import rule87 from './rare_process_by_host_linux.json'; -import rule88 from './rare_process_by_host_windows.json'; -import rule89 from './sqlmap_user_agent.json'; -import rule90 from './suspicious_login_activity.json'; -import rule91 from './windows_anomalous_network_activity.json'; -import rule92 from './windows_anomalous_path_activity.json'; -import rule93 from './windows_anomalous_process_all_hosts.json'; -import rule94 from './windows_anomalous_process_creation.json'; -import rule95 from './windows_anomalous_script.json'; -import rule96 from './windows_anomalous_service.json'; -import rule97 from './windows_anomalous_user_name.json'; -import rule98 from './windows_certutil_network_connection.json'; -import rule99 from './windows_command_prompt_connecting_to_the_internet.json'; -import rule100 from './windows_command_shell_started_by_powershell.json'; -import rule101 from './windows_command_shell_started_by_svchost.json'; -import rule102 from './windows_credential_dumping_msbuild.json'; -import rule103 from './windows_cve_2020_0601.json'; -import rule104 from './windows_defense_evasion_via_filter_manager.json'; -import rule105 from './windows_execution_msbuild_started_by_office_app.json'; -import rule106 from './windows_execution_msbuild_started_by_script.json'; -import rule107 from './windows_execution_msbuild_started_by_system_process.json'; -import rule108 from './windows_execution_msbuild_started_renamed.json'; -import rule109 from './windows_execution_msbuild_started_unusal_process.json'; -import rule110 from './windows_execution_via_compiled_html_file.json'; -import rule111 from './windows_execution_via_net_com_assemblies.json'; -import rule112 from './windows_execution_via_trusted_developer_utilities.json'; -import rule113 from './windows_html_help_executable_program_connecting_to_the_internet.json'; -import rule114 from './windows_injection_msbuild.json'; -import rule115 from './windows_misc_lolbin_connecting_to_the_internet.json'; -import rule116 from './windows_modification_of_boot_config.json'; -import rule117 from './windows_msxsl_network.json'; -import rule118 from './windows_net_command_system_account.json'; -import rule119 from './windows_persistence_via_application_shimming.json'; -import rule120 from './windows_priv_escalation_via_accessibility_features.json'; -import rule121 from './windows_process_discovery_via_tasklist_command.json'; -import rule122 from './windows_rare_user_runas_event.json'; -import rule123 from './windows_rare_user_type10_remote_login.json'; -import rule124 from './windows_register_server_program_connecting_to_the_internet.json'; -import rule125 from './windows_suspicious_pdf_reader.json'; -import rule126 from './windows_uac_bypass_event_viewer.json'; -import rule127 from './windows_whoami_command_activity.json'; - +import rule47 from './linux_attempt_to_disable_iptables_or_firewall.json'; +import rule48 from './linux_attempt_to_disable_syslog_service.json'; +import rule49 from './linux_base16_or_base32_encoding_or_decoding_activity.json'; +import rule50 from './linux_base64_encoding_or_decoding_activity.json'; +import rule51 from './linux_disable_selinux_attempt.json'; +import rule52 from './linux_file_deletion_via_shred.json'; +import rule53 from './linux_file_mod_writable_dir.json'; +import rule54 from './linux_hex_encoding_or_decoding_activity.json'; +import rule55 from './linux_hping_activity.json'; +import rule56 from './linux_iodine_activity.json'; +import rule57 from './linux_kernel_module_activity.json'; +import rule58 from './linux_kernel_module_enumeration.json'; +import rule59 from './linux_kernel_module_removal.json'; +import rule60 from './linux_mknod_activity.json'; +import rule61 from './linux_netcat_network_connection.json'; +import rule62 from './linux_nmap_activity.json'; +import rule63 from './linux_nping_activity.json'; +import rule64 from './linux_perl_tty_shell.json'; +import rule65 from './linux_process_started_in_temp_directory.json'; +import rule66 from './linux_python_tty_shell.json'; +import rule67 from './linux_setgid_bit_set_via_chmod.json'; +import rule68 from './linux_setuid_bit_set_via_chmod.json'; +import rule69 from './linux_shell_activity_by_web_server.json'; +import rule70 from './linux_socat_activity.json'; +import rule71 from './linux_strace_activity.json'; +import rule72 from './linux_sudoers_file_mod.json'; +import rule73 from './linux_tcpdump_activity.json'; +import rule74 from './linux_telnet_network_activity_external.json'; +import rule75 from './linux_telnet_network_activity_internal.json'; +import rule76 from './linux_virtual_machine_fingerprinting.json'; +import rule77 from './linux_whoami_commmand.json'; +import rule78 from './network_dns_directly_to_the_internet.json'; +import rule79 from './network_ftp_file_transfer_protocol_activity_to_the_internet.json'; +import rule80 from './network_irc_internet_relay_chat_protocol_activity_to_the_internet.json'; +import rule81 from './network_nat_traversal_port_activity.json'; +import rule82 from './network_port_26_activity.json'; +import rule83 from './network_port_8000_activity_to_the_internet.json'; +import rule84 from './network_pptp_point_to_point_tunneling_protocol_activity.json'; +import rule85 from './network_proxy_port_activity_to_the_internet.json'; +import rule86 from './network_rdp_remote_desktop_protocol_from_the_internet.json'; +import rule87 from './network_rdp_remote_desktop_protocol_to_the_internet.json'; +import rule88 from './network_rpc_remote_procedure_call_from_the_internet.json'; +import rule89 from './network_rpc_remote_procedure_call_to_the_internet.json'; +import rule90 from './network_smb_windows_file_sharing_activity_to_the_internet.json'; +import rule91 from './network_smtp_to_the_internet.json'; +import rule92 from './network_sql_server_port_activity_to_the_internet.json'; +import rule93 from './network_ssh_secure_shell_from_the_internet.json'; +import rule94 from './network_ssh_secure_shell_to_the_internet.json'; +import rule95 from './network_telnet_port_activity.json'; +import rule96 from './network_tor_activity_to_the_internet.json'; +import rule97 from './network_vnc_virtual_network_computing_from_the_internet.json'; +import rule98 from './network_vnc_virtual_network_computing_to_the_internet.json'; +import rule99 from './null_user_agent.json'; +import rule100 from './packetbeat_dns_tunneling.json'; +import rule101 from './packetbeat_rare_dns_question.json'; +import rule102 from './packetbeat_rare_server_domain.json'; +import rule103 from './packetbeat_rare_urls.json'; +import rule104 from './packetbeat_rare_user_agent.json'; +import rule105 from './rare_process_by_host_linux.json'; +import rule106 from './rare_process_by_host_windows.json'; +import rule107 from './sqlmap_user_agent.json'; +import rule108 from './suspicious_login_activity.json'; +import rule109 from './windows_anomalous_network_activity.json'; +import rule110 from './windows_anomalous_path_activity.json'; +import rule111 from './windows_anomalous_process_all_hosts.json'; +import rule112 from './windows_anomalous_process_creation.json'; +import rule113 from './windows_anomalous_script.json'; +import rule114 from './windows_anomalous_service.json'; +import rule115 from './windows_anomalous_user_name.json'; +import rule116 from './windows_certutil_network_connection.json'; +import rule117 from './windows_command_prompt_connecting_to_the_internet.json'; +import rule118 from './windows_command_shell_started_by_powershell.json'; +import rule119 from './windows_command_shell_started_by_svchost.json'; +import rule120 from './windows_credential_dumping_msbuild.json'; +import rule121 from './windows_cve_2020_0601.json'; +import rule122 from './windows_defense_evasion_via_filter_manager.json'; +import rule123 from './windows_execution_msbuild_started_by_office_app.json'; +import rule124 from './windows_execution_msbuild_started_by_script.json'; +import rule125 from './windows_execution_msbuild_started_by_system_process.json'; +import rule126 from './windows_execution_msbuild_started_renamed.json'; +import rule127 from './windows_execution_msbuild_started_unusal_process.json'; +import rule128 from './windows_execution_via_compiled_html_file.json'; +import rule129 from './windows_execution_via_net_com_assemblies.json'; +import rule130 from './windows_execution_via_trusted_developer_utilities.json'; +import rule131 from './windows_html_help_executable_program_connecting_to_the_internet.json'; +import rule132 from './windows_injection_msbuild.json'; +import rule133 from './windows_misc_lolbin_connecting_to_the_internet.json'; +import rule134 from './windows_modification_of_boot_config.json'; +import rule135 from './windows_msxsl_network.json'; +import rule136 from './windows_net_command_system_account.json'; +import rule137 from './windows_persistence_via_application_shimming.json'; +import rule138 from './windows_priv_escalation_via_accessibility_features.json'; +import rule139 from './windows_process_discovery_via_tasklist_command.json'; +import rule140 from './windows_rare_user_runas_event.json'; +import rule141 from './windows_rare_user_type10_remote_login.json'; +import rule142 from './windows_register_server_program_connecting_to_the_internet.json'; +import rule143 from './windows_suspicious_pdf_reader.json'; +import rule144 from './windows_uac_bypass_event_viewer.json'; +import rule145 from './windows_whoami_command_activity.json'; export const rawRules = [ rule1, rule2, @@ -263,4 +280,22 @@ export const rawRules = [ rule125, rule126, rule127, + rule128, + rule129, + rule130, + rule131, + rule132, + rule133, + rule134, + rule135, + rule136, + rule137, + rule138, + rule139, + rule140, + rule141, + rule142, + rule143, + rule144, + rule145, ]; diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json index 41f38173dba33..d910f83b0c8bd 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_activity.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "linux_anomalous_network_activity_ecs", "name": "Unusual Linux Network Activity", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "ML" ], "type": "machine_learning", - "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Linux process for which network activity is rare and unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business or maintenance process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json index d435d4c10f05c..aa0d1cb125aed 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_port_activity.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json index 0b82ce99d0b7f..5d137b81d1314 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_service.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json index 26af34e18a4c8..3732e575a2e41 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_network_url_activity.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json index 103171bcdfe50..259f0147953ad 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_process_all_hosts.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "linux_anomalous_process_all_hosts_ecs", "name": "Anomalous Process For a Linux Population", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for all of the monitored Linux hosts for which Auditbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "ML" ], "type": "machine_learning", - "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for all of the monitored Linux hosts for which Auditbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json index 6642bb5d73fbd..2e7bd0d1d99d7 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_anomalous_user_name.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "linux_anomalous_user_name_ecs", "name": "Unusual Linux Username", + "note": "### Investigating an Unusual Linux User ###\nSignals from this rule indicate activity for a Linux user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to troubleshooting or debugging activity by a developer or site reliability engineer?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "ML" ], "type": "machine_learning", - "note": "### Investigating an Unusual Linux User ###\nSignals from this rule indicate activity for a Linux user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to troubleshooting or debugging activity by a developer or site reliability engineer?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_iptables_or_firewall.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_iptables_or_firewall.json new file mode 100644 index 0000000000000..77d0ddc22ff40 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_iptables_or_firewall.json @@ -0,0 +1,35 @@ +{ + "description": "Adversaries may attempt to disable the iptables or firewall service in an attempt to affect how a host is allowed to receive or send network traffic.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Attempt to Disable IPTables or Firewall", + "query": "event.action:(executed or process_started) and (process.name:service and process.args:stop or process.name:chkconfig and process.args:off) and process.args:(ip6tables or iptables) or process.name:systemctl and process.args:(firewalld and (disable or stop or kill))", + "risk_score": 47, + "rule_id": "125417b8-d3df-479f-8418-12d7e034fee3", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1089", + "name": "Disabling Security Tools", + "reference": "https://attack.mitre.org/techniques/T1089/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_syslog_service.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_syslog_service.json new file mode 100644 index 0000000000000..d4584035d53b4 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_attempt_to_disable_syslog_service.json @@ -0,0 +1,35 @@ +{ + "description": "Adversaries may attempt to disable the syslog service in an attempt to an attempt to disrupt event logging and evade detection by security controls.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Attempt to Disable Syslog Service", + "query": "event.action:(executed or process_started) and ((process.name:service and process.args:stop) or (process.name:chkconfig and process.args:off) or (process.name:systemctl and process.args:(disable or stop or kill))) and process.args:(syslog or rsyslog or \"syslog-ng\")", + "risk_score": 47, + "rule_id": "2f8a1226-5720-437d-9c20-e0029deb6194", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1089", + "name": "Disabling Security Tools", + "reference": "https://attack.mitre.org/techniques/T1089/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base16_or_base32_encoding_or_decoding_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base16_or_base32_encoding_or_decoding_activity.json new file mode 100644 index 0000000000000..9518138ad6799 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base16_or_base32_encoding_or_decoding_activity.json @@ -0,0 +1,53 @@ +{ + "description": "Adversaries may encode/decode data in an attempt to evade detection by host- or network-based security controls.", + "false_positives": [ + "Automated tools such as Jenkins may encode or decode files as part of their normal behavior. These events can be filtered by the process executable or username values." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Base16 or Base32 Encoding/Decoding Activity", + "query": "event.action:(executed or process_started) and process.name:(base16 or base32 or base32plain or base32hex)", + "risk_score": 21, + "rule_id": "debff20a-46bc-4a4d-bae5-5cdd14222795", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1140", + "name": "Deobfuscate/Decode Files or Information", + "reference": "https://attack.mitre.org/techniques/T1140/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1027", + "name": "Obfuscated Files or Information", + "reference": "https://attack.mitre.org/techniques/T1027/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base64_encoding_or_decoding_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base64_encoding_or_decoding_activity.json new file mode 100644 index 0000000000000..37f3e3eaccd90 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_base64_encoding_or_decoding_activity.json @@ -0,0 +1,53 @@ +{ + "description": "Adversaries may encode/decode data in an attempt to evade detection by host- or network-based security controls.", + "false_positives": [ + "Automated tools such as Jenkins may encode or decode files as part of their normal behavior. These events can be filtered by the process executable or username values." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Base64 Encoding/Decoding Activity", + "query": "event.action:(executed or process_started) and process.name:(base64 or base64plain or base64url or base64mime or base64pem)", + "risk_score": 21, + "rule_id": "97f22dab-84e8-409d-955e-dacd1d31670b", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1140", + "name": "Deobfuscate/Decode Files or Information", + "reference": "https://attack.mitre.org/techniques/T1140/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1027", + "name": "Obfuscated Files or Information", + "reference": "https://attack.mitre.org/techniques/T1027/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_disable_selinux_attempt.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_disable_selinux_attempt.json new file mode 100644 index 0000000000000..d33331cd4f8d4 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_disable_selinux_attempt.json @@ -0,0 +1,35 @@ +{ + "description": "Identifies potential attempts to disable Security-Enhanced Linux (SELinux), which is a Linux kernel security feature to support access control policies. Adversaries may disable security tools to avoid possible detection of their tools and activities.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Potential Disabling of SELinux", + "query": "event.action:executed and process.name:setenforce and process.args:0", + "risk_score": 47, + "rule_id": "eb9eb8ba-a983-41d9-9c93-a1c05112ca5e", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1089", + "name": "Disabling Security Tools", + "reference": "https://attack.mitre.org/techniques/T1089/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_deletion_via_shred.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_deletion_via_shred.json new file mode 100644 index 0000000000000..4fd72a212f0ba --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_deletion_via_shred.json @@ -0,0 +1,35 @@ +{ + "description": "Malware or other files dropped or created on a system by an adversary may leave traces behind as to what was done within a network and how. Adversaries may remove these files over the course of an intrusion to keep their footprint low or remove them at the end as part of the post-intrusion cleanup process.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "File Deletion via Shred", + "query": "event.action:(executed or process_started) and process.name:shred and process.args:(\"-u\" or \"--remove\" or \"-z\" or \"--zero\")", + "risk_score": 21, + "rule_id": "a1329140-8de3-4445-9f87-908fb6d824f4", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1107", + "name": "File Deletion", + "reference": "https://attack.mitre.org/techniques/T1107/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_mod_writable_dir.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_mod_writable_dir.json new file mode 100644 index 0000000000000..66c5848b17707 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_file_mod_writable_dir.json @@ -0,0 +1,38 @@ +{ + "description": "Identifies file permission modifications in common writable directories by a non-root user. Adversaries often drop files or payloads into a writable directory and change permissions prior to execution.", + "false_positives": [ + "Certain programs or applications may modify files or change ownership in writable directories. These can be exempted by username." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "File Permission Modification in Writable Directory", + "query": "event.action:executed and process.name:(chmod or chown or chattr or chgrp) and process.working_directory:(/tmp or /var/tmp or /dev/shm) and not user.name:root", + "risk_score": 21, + "rule_id": "9f9a2a82-93a8-4b1a-8778-1780895626d4", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1222", + "name": "File and Directory Permissions Modification", + "reference": "https://attack.mitre.org/techniques/T1222/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hex_encoding_or_decoding_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hex_encoding_or_decoding_activity.json new file mode 100644 index 0000000000000..a67d310d2ad81 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hex_encoding_or_decoding_activity.json @@ -0,0 +1,53 @@ +{ + "description": "Adversaries may encode/decode data in an attempt to evade detection by host- or network-based security controls.", + "false_positives": [ + "Automated tools such as Jenkins may encode or decode files as part of their normal behavior. These events can be filtered by the process executable or username values." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Hex Encoding/Decoding Activity", + "query": "event.action:(executed or process_started) and process.name:(hex or xxd)", + "risk_score": 21, + "rule_id": "a9198571-b135-4a76-b055-e3e5a476fd83", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1140", + "name": "Deobfuscate/Decode Files or Information", + "reference": "https://attack.mitre.org/techniques/T1140/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1027", + "name": "Obfuscated Files or Information", + "reference": "https://attack.mitre.org/techniques/T1027/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json index 04a56241ea6f6..bd954683723f4 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json index 80358cc775e3b..63b0155bbd82c 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json index b50fcc4c9980b..95fe337fbfd1b 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_activity.json @@ -38,4 +38,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_enumeration.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_enumeration.json new file mode 100644 index 0000000000000..85564506bcff9 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_enumeration.json @@ -0,0 +1,38 @@ +{ + "description": "Loadable Kernel Modules (or LKMs) are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system. This identifies attempts to enumerate information about a kernel module.", + "false_positives": [ + "Security tools and device drivers may run these programs in order to enumerate kernel modules. Use of these programs by ordinary users is uncommon. These can be exempted by process name or username." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Enumeration of Kernel Modules", + "query": "event.action:executed and process.args:(kmod and list and sudo or sudo and (depmod or lsmod or modinfo))", + "risk_score": 47, + "rule_id": "2d8043ed-5bda-4caf-801c-c1feb7410504", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1082", + "name": "System Information Discovery", + "reference": "https://attack.mitre.org/techniques/T1082/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_removal.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_removal.json new file mode 100644 index 0000000000000..bb88a2acad53d --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_kernel_module_removal.json @@ -0,0 +1,56 @@ +{ + "description": "Kernel modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system. This rule identifies attempts to remove a kernel module.", + "false_positives": [ + "There is usually no reason to remove modules, but some buggy modules require it. These can be exempted by username. Note that some Linux distributions are not built to support the removal of modules at all." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Kernel Module Removal", + "query": "event.action:executed and process.args:(rmmod and sudo or modprobe and sudo and (\"--remove\" or \"-r\"))", + "references": [ + "http://man7.org/linux/man-pages/man8/modprobe.8.html" + ], + "risk_score": 73, + "rule_id": "cd66a5af-e34b-4bb0-8931-57d0a043f2ef", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1089", + "name": "Disabling Security Tools", + "reference": "https://attack.mitre.org/techniques/T1089/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0003", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0003/" + }, + "technique": [ + { + "id": "T1215", + "name": "Kernel Modules and Extensions", + "reference": "https://attack.mitre.org/techniques/T1215/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json index d65440e95ff17..21208ade670ee 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_mknod_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json index df8e46be7a1c3..caacef3b33deb 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_netcat_network_connection.json @@ -23,4 +23,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json index 2e5c899ebc625..99324460cc00a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nmap_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json index 168b30121c4bb..b4d44c65cd89c 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_perl_tty_shell.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_perl_tty_shell.json new file mode 100644 index 0000000000000..2f003f8ec9d03 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_perl_tty_shell.json @@ -0,0 +1,35 @@ +{ + "description": "Identifies when a terminal (tty) is spawned via Perl. Attackers may upgrade a simple reverse shell to a fully interactive tty after obtaining initial access to a host.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Interactive Terminal Spawned via Perl", + "query": "event.action:executed and process.name:perl and process.args:(\"exec \\\"/bin/sh\\\";\" or \"exec \\\"/bin/dash\\\";\" or \"exec \\\"/bin/bash\\\";\")", + "risk_score": 73, + "rule_id": "05e5a668-7b51-4a67-93ab-e9af405c9ef3", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json index 0865ac6c70cb2..c20a41ac91d02 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json @@ -18,4 +18,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_python_tty_shell.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_python_tty_shell.json new file mode 100644 index 0000000000000..42e014e919cad --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_python_tty_shell.json @@ -0,0 +1,35 @@ +{ + "description": "Identifies when a terminal (tty) is spawned via Python. Attackers may upgrade a simple reverse shell to a fully interactive tty after obtaining initial access to a host.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Interactive Terminal Spawned via Python", + "query": "event.action:executed and process.name:python and process.args:(\"import pty; pty.spawn(\\\"/bin/sh\\\")\" or \"import pty; pty.spawn(\\\"/bin/dash\\\")\" or \"import pty; pty.spawn(\\\"/bin/bash\\\")\")", + "risk_score": 73, + "rule_id": "d76b02ef-fc95-4001-9297-01cb7412232f", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command-Line Interface", + "reference": "https://attack.mitre.org/techniques/T1059/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setgid_bit_set_via_chmod.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setgid_bit_set_via_chmod.json new file mode 100644 index 0000000000000..c104330348596 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setgid_bit_set_via_chmod.json @@ -0,0 +1,51 @@ +{ + "description": "An adversary may add the setgid bit to a file or directory in order to run a file with the privileges of the owning group. An adversary can take advantage of this to either do a shell escape or exploit a vulnerability in an application with the setgid bit to get code running in a different user\u2019s context. Additionally, adversaries can use this mechanism on their own malware to make sure they're able to execute in elevated contexts in the future.", + "index": [ + "auditbeat-*" + ], + "language": "lucene", + "max_signals": 33, + "name": "Setgid Bit Set via chmod", + "query": "event.action:(executed OR process_started) AND process.name:chmod AND process.args:(g+s OR /2[0-9]{3}/) AND NOT user.name:root", + "risk_score": 21, + "rule_id": "3a86e085-094c-412d-97ff-2439731e59cb", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1166", + "name": "Setuid and Setgid", + "reference": "https://attack.mitre.org/techniques/T1166/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1166", + "name": "Setuid and Setgid", + "reference": "https://attack.mitre.org/techniques/T1166/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setuid_bit_set_via_chmod.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setuid_bit_set_via_chmod.json new file mode 100644 index 0000000000000..72b62b67aa2d4 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_setuid_bit_set_via_chmod.json @@ -0,0 +1,51 @@ +{ + "description": "An adversary may add the setuid bit to a file or directory in order to run a file with the privileges of the owning user. An adversary can take advantage of this to either do a shell escape or exploit a vulnerability in an application with the setuid bit to get code running in a different user\u2019s context. Additionally, adversaries can use this mechanism on their own malware to make sure they're able to execute in elevated contexts in the future.", + "index": [ + "auditbeat-*" + ], + "language": "lucene", + "max_signals": 33, + "name": "Setuid Bit Set via chmod", + "query": "event.action:(executed OR process_started) AND process.name:chmod AND process.args:(u+s OR /4[0-9]{3}/) AND NOT user.name:root", + "risk_score": 21, + "rule_id": "8a1b0278-0f9a-487d-96bd-d4833298e87a", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1166", + "name": "Setuid and Setgid", + "reference": "https://attack.mitre.org/techniques/T1166/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Persistence", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1166", + "name": "Setuid and Setgid", + "reference": "https://attack.mitre.org/techniques/T1166/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json index e9c4c95bb9284..4d6000bda3b01 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_shell_activity_by_web_server.json @@ -8,7 +8,7 @@ ], "language": "kuery", "name": "Potential Shell via Web Server", - "query": "process.name:bash and user.name:(apache or www or www-data) and event.action:executed", + "query": "process.name:(bash or dash) and user.name:(apache or nginx or www or \"www-data\") and event.action:executed", "references": [ "https://pentestlab.blog/tag/web-shell/" ], @@ -37,5 +37,5 @@ } ], "type": "query", - "version": 2 -} \ No newline at end of file + "version": 3 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json index 404fea63aff94..b0f9a19bfacaa 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_socat_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json index fbdfa9e66682d..9e449ebfdfd81 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_sudoers_file_mod.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_sudoers_file_mod.json new file mode 100644 index 0000000000000..3cb9259e92132 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_sudoers_file_mod.json @@ -0,0 +1,35 @@ +{ + "description": "A sudoers file specifies the commands that users or groups can run and from which terminals. Adversaries can take advantage of these configurations to execute commands as other users or spawn processes with higher privileges.", + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Sudoers File Modification", + "query": "event.module:file_integrity and event.action:updated and file.path:/etc/sudoers", + "risk_score": 21, + "rule_id": "931e25a5-0f5e-4ae0-ba0d-9e94eff7e3a4", + "severity": "low", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0004", + "name": "Privilege Escalation", + "reference": "https://attack.mitre.org/tactics/TA0004/" + }, + "technique": [ + { + "id": "T1169", + "name": "Sudo", + "reference": "https://attack.mitre.org/techniques/T1169/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json index 82771074e7c29..b372645cc492a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_tcpdump_activity.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_external.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_external.json new file mode 100644 index 0000000000000..9f6b80b8bf1ef --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_external.json @@ -0,0 +1,38 @@ +{ + "description": "Telnet provides a command line interface for communication with a remote device or server. This rule identifies Telnet network connections to publicly routable IP addresses.", + "false_positives": [ + "Telnet can be used for both benign or malicious purposes. Telnet is included by default in some Linux distributions, so its presence is not inherently suspicious. The use of Telnet to manage devices remotely has declined in recent years in favor of more secure protocols such as SSH. Telnet usage by non-automated tools or frameworks may be suspicious." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Connection to External Network via Telnet", + "query": "event.action:(\"connected-to\" or \"network_flow\") and process.name:telnet and not destination.ip:(127.0.0.0/8 or 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 or \"FE80::/10\" or \"::1/128\")", + "risk_score": 47, + "rule_id": "e19e64ee-130e-4c07-961f-8a339f0b8362", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1021", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_internal.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_internal.json new file mode 100644 index 0000000000000..a2e94f1d2d015 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_telnet_network_activity_internal.json @@ -0,0 +1,38 @@ +{ + "description": "Telnet provides a command line interface for communication with a remote device or server. This rule identifies Telnet network connections to non-publicly routable IP addresses.", + "false_positives": [ + "Telnet can be used for both benign or malicious purposes. Telnet is included by default in some Linux distributions, so its presence is not inherently suspicious. The use of Telnet to manage devices remotely has declined in recent years in favor of more secure protocols such as SSH. Telnet usage by non-automated tools or frameworks may be suspicious." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Connection to Internal Network via Telnet", + "query": "event.action:(\"connected-to\" or \"network_flow\") and process.name:telnet and destination.ip:((10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 or \"FE80::/10\") and not (127.0.0.0/8 or \"::1/128\"))", + "risk_score": 47, + "rule_id": "1b21abcc-4d9f-4b08-a7f5-316f5f94b973", + "severity": "medium", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0008", + "name": "Lateral Movement", + "reference": "https://attack.mitre.org/tactics/TA0008/" + }, + "technique": [ + { + "id": "T1021", + "name": "Remote Services", + "reference": "https://attack.mitre.org/techniques/T1021/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_virtual_machine_fingerprinting.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_virtual_machine_fingerprinting.json new file mode 100644 index 0000000000000..28c4b6d6ee0e5 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_virtual_machine_fingerprinting.json @@ -0,0 +1,38 @@ +{ + "description": "An adversary may attempt to get detailed information about the operating system and hardware. This rule identifies common locations used to discover virtual machine hardware by a non-root user. This technique has been used by the Pupy RAT and other malware.", + "false_positives": [ + "Certain tools or automated software may enumerate hardware information. These tools can be exempted via user name or process arguments to eliminate potential noise." + ], + "index": [ + "auditbeat-*" + ], + "language": "kuery", + "name": "Virtual Machine Fingerprinting", + "query": "event.action:executed and process.args:(\"/sys/class/dmi/id/bios_version\" or \"/sys/class/dmi/id/product_name\" or \"/sys/class/dmi/id/chassis_vendor\" or \"/proc/scsi/scsi\" or \"/proc/ide/hd0/model\") and not user.name:root", + "risk_score": 73, + "rule_id": "5b03c9fb-9945-4d2f-9568-fd690fee3fba", + "severity": "high", + "tags": [ + "Elastic", + "Linux" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0007", + "name": "Discovery", + "reference": "https://attack.mitre.org/tactics/TA0007/" + }, + "technique": [ + { + "id": "T1082", + "name": "System Information Discovery", + "reference": "https://attack.mitre.org/techniques/T1082/" + } + ] + } + ], + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json index 7e7f041581eb0..e96c8dc3887e0 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/linux_whoami_commmand.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json index e08d681d14463..1ffabbc876e2e 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_dns_directly_to_the_internet.json @@ -39,4 +39,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json index 24c3bad817227..0649d408a5c22 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ftp_file_transfer_protocol_activity_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json index bf286d4cab506..bdabfa4d5f38f 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_irc_internet_relay_chat_protocol_activity_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json index 61c1e3d47cf7a..63bdd2b83e3bc 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_nat_traversal_port_activity.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json index a9a39b61884c5..df809d2225352 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_26_activity.json @@ -54,4 +54,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json index 2f1390411f97b..11b711d8f7464 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_port_8000_activity_to_the_internet.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json index f7170d8d33a51..87d37b77f53b4 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_pptp_point_to_point_tunneling_protocol_activity.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json index da4319cf15307..35ba1ca806296 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_proxy_port_activity_to_the_internet.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json index d3b65a36f084b..7b0c9b2927cab 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_from_the_internet.json @@ -65,4 +65,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json index 79618a867c73f..17d00ebff4603 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rdp_remote_desktop_protocol_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json index da1e46750f3bd..719d0e39e94cd 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_from_the_internet.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json index d07d19b8fffee..a7791047cab26 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_rpc_remote_procedure_call_to_the_internet.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json index 93a4b0ebbbd8e..eca200e318c42 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smb_windows_file_sharing_activity_to_the_internet.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json index ca287605490ef..c05efa1c0e26b 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_smtp_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json index 3a5bd5bff98f5..5ed7ca4112015 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_sql_server_port_activity_to_the_internet.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json index 429a91183e88a..2bd9a3f63ee8c 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_from_the_internet.json @@ -65,4 +65,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json index a260245b4dade..6512a1627db89 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_ssh_secure_shell_to_the_internet.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json index 4cfe15683c825..af60c991ceea2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_telnet_port_activity.json @@ -65,4 +65,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json index 8c8bb809c9fec..ff2ead0eaaf49 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_tor_activity_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json index 4204a4fe62e88..7fac7938579ca 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_from_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json index 898282e36df19..0a620d355b9ae 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/network_vnc_virtual_network_computing_to_the_internet.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 3 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json index 01246de5595e9..489077c9a5516 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/null_user_agent.json @@ -39,4 +39,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json index 765515ffda27c..c5cf6385afaf0 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_dns_tunneling.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json index 79c30c5b38378..4623639b6e8b7 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_dns_question.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json index 7b14ad62f6c93..dd14191d30df2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_server_domain.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json index 76767545e794a..386e00054c2cc 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_urls.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json index 1dc49203f31c1..a68c43b228303 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/packetbeat_rare_user_agent.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json index 8ae1b84aaf199..9d9fb5e4a0a8d 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_linux.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "rare_process_by_host_linux_ecs", "name": "Unusual Process For a Linux Host", + "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "ML" ], "type": "machine_learning", - "note": "### Investigating an Unusual Linux Process ###\nSignals from this rule indicate the presence of a Linux process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json index 879cee388f5dd..0c1d097a73dc2 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/rare_process_by_host_windows.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "rare_process_by_host_windows_ecs", "name": "Unusual Process For a Windows Host", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "Windows" ], "type": "machine_learning", - "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json index 10412c19da1b1..3ad82d14be7a7 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/sqlmap_user_agent.json @@ -21,4 +21,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json index 4b94fdc6da147..b3c3f2d76a8c9 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/suspicious_login_activity.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json index 1092bcb20bcc3..0a85fee3de436 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_network_activity.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "windows_anomalous_network_activity_ecs", "name": "Unusual Windows Network Activity", + "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Windows process for which network activity is very unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses, protocol and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "Windows" ], "type": "machine_learning", - "note": "### Investigating Unusual Network Activity ###\nSignals from this rule indicate the presence of network activity from a Windows process for which network activity is very unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses, protocol and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected? \n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json index 8a88607b9d5c9..2652915d21d85 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_path_activity.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json index f9adfeb830618..4e70426a4faf8 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_all_hosts.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "windows_anomalous_process_all_hosts_ecs", "name": "Anomalous Process For a Windows Population", + "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for all of the Windows hosts for which Winlogbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "Windows" ], "type": "machine_learning", - "note": "### Investigating an Unusual Windows Process ###\nSignals from this rule indicate the presence of a Windows process that is rare and unusual for all of the Windows hosts for which Winlogbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package. \n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json index 98a078ccea4a4..4742fd951f471 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_process_creation.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json index 564ca1782526f..bc38877a00ad0 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_script.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json index afef569f4ebb4..92c4b22823120 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_service.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json index a0c6ff5c938f1..9ad05eda8f518 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_anomalous_user_name.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "windows_anomalous_user_name_ecs", "name": "Unusual Windows Username", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a Windows user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to occasional troubleshooting or support activity?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "Windows" ], "type": "machine_learning", - "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a Windows user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to occasional troubleshooting or support activity?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json index 52a373e3aeb77..82db7de3d3130 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_certutil_network_connection.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json index 2bee265a74e11..51fceacddb3c9 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_prompt_connecting_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json index d8f91dba7dd89..8e88549a44ada 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_powershell.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json index 6fd194ee2fa22..f36f853a8e760 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_command_shell_started_by_svchost.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json index 43050e2769a24..4ff7891438554 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_credential_dumping_msbuild.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json index f5eb37c70d268..b42427a912cbb 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_cve_2020_0601.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json index 0e8c5a5f2f631..ba684c4d721ee 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_defense_evasion_via_filter_manager.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_office_app.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_office_app.json index 72e02f8718d03..78f34c15bbd31 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_office_app.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_office_app.json @@ -53,4 +53,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_script.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_script.json index ad519f1516aa6..3952a4680a523 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_script.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_script.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_system_process.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_system_process.json index 1bbce904f2518..a2e29c3900144 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_system_process.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_by_system_process.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_renamed.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_renamed.json index eea4b3b4efe10..1e63b259a86ec 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_renamed.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_renamed.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_unusal_process.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_unusal_process.json index 81ea14e265388..117d5982421a4 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_unusal_process.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_msbuild_started_unusal_process.json @@ -38,4 +38,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json index 7755ff0233f7c..07c87531c4a4a 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_compiled_html_file.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json index d6acb81c10e3f..fb59cff68410e 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_net_com_assemblies.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json index 87e38febb0743..202bfc6b46afc 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_execution_via_trusted_developer_utilities.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json index 6c8cd0673256a..906995b3b6662 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_html_help_executable_program_connecting_to_the_internet.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_injection_msbuild.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_injection_msbuild.json index c6310c12ed974..32a8f50c4b911 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_injection_msbuild.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_injection_msbuild.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json index a0e311d8eb154..361a3e99b4dbd 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_misc_lolbin_connecting_to_the_internet.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json index 045a9789b1260..66195acafa5cb 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_modification_of_boot_config.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json index e80dcde1e398d..735ae0b2d6a7b 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_msxsl_network.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json index c2379142df002..b2770ac2383fd 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_net_command_system_account.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json index 2f44727f9e6f0..5b77fdb01a605 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_persistence_via_application_shimming.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json index aeff071ed4514..59ae2f6ad3bb8 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_priv_escalation_via_accessibility_features.json @@ -47,4 +47,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json index 3a883fa51b763..489c8a47561b5 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_process_discovery_via_tasklist_command.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json index febaa57443f76..a227b36064a9d 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_runas_event.json @@ -21,4 +21,4 @@ ], "type": "machine_learning", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json index 7318364c3aac2..15241d7869c00 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_rare_user_type10_remote_login.json @@ -8,6 +8,7 @@ "interval": "15m", "machine_learning_job_id": "windows_rare_user_type10_remote_login", "name": "Unusual Windows Remote User", + "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a rare and unusual Windows RDP (remote desktop) user. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is the user part of a group who normally logs into Windows hosts using RDP (remote desktop protocol)? Is this logon activity part of an expected workflow for the user? \n- Consider the source of the login. If the source is remote, could this be related to occasional troubleshooting or support activity by a vendor or an employee working remotely?", "references": [ "https://www.elastic.co/guide/en/siem/guide/current/prebuilt-ml-jobs.html" ], @@ -20,6 +21,5 @@ "Windows" ], "type": "machine_learning", - "note": "### Investigating an Unusual Windows User ###\nSignals from this rule indicate activity for a rare and unusual Windows RDP (remote desktop) user. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is the user part of a group who normally logs into Windows hosts using RDP (remote desktop protocol)? Is this logon activity part of an expected workflow for the user? \n- Consider the source of the login. If the source is remote, could this be related to occasional troubleshooting or support activity by a vendor or an employee working remotely?", "version": 1 } diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json index 1e061f2ef9463..f6fc38f963640 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_register_server_program_connecting_to_the_internet.json @@ -50,4 +50,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_pdf_reader.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_pdf_reader.json index 9d4c2438acfb9..6c2b167a76ee4 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_pdf_reader.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_suspicious_pdf_reader.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json index df7a6fe1285d1..1fb44f0c842de 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_uac_bypass_event_viewer.json @@ -32,4 +32,4 @@ ], "type": "query", "version": 1 -} \ No newline at end of file +} diff --git a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json index 93ce1f83dd64e..c01396dd51527 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json +++ b/x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules/windows_whoami_command_activity.json @@ -35,4 +35,4 @@ ], "type": "query", "version": 2 -} \ No newline at end of file +} From 4896b65c98be61e11d08f1ae8729d19f3edd0dba Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 5 May 2020 12:15:15 -0700 Subject: [PATCH 29/72] [APM] Service maps anomaly detection status in popover (#65217) * Adds ML status to the service maps popover. Modifies the query a bit to get the actual vs typical values necessary to generate a proper anomaly description * fixed failures and updated tests * component clean up * makes the ML link open in a new window * - Closes #64278 by removing the framework badge. - changes anomaly score display to integer formatting - update link test to 'View anomalies' * - Closes #65244 by displaying a message for services without anomalies detected - removes unecessary service framework name in service map queries - adds date range filter for anomaly detection --- x-pack/plugins/apm/common/service_map.ts | 2 - .../components/app/ServiceMap/Cytoscape.tsx | 5 + .../app/ServiceMap/Popover/Contents.tsx | 133 +++- .../ServiceMap/Popover/Popover.stories.tsx | 1 - .../Popover/ServiceMetricFetcher.tsx | 10 +- .../ServiceMap/Popover/ServiceMetricList.tsx | 11 +- .../cytoscape-layout-test-response.json | 642 +++++++++--------- .../app/ServiceMap/cytoscapeOptions.ts | 23 +- .../MachineLearningLinks/MLJobLink.test.tsx | 14 +- .../Links/MachineLearningLinks/MLJobLink.tsx | 27 +- .../Links/MachineLearningLinks/MLLink.tsx | 12 +- .../apm/server/lib/helpers/range_filter.ts | 8 +- .../dedupe_connections/index.test.ts | 3 - .../server/lib/service_map/get_service_map.ts | 41 +- .../server/lib/service_map/ml_helpers.test.ts | 48 +- .../apm/server/lib/service_map/ml_helpers.ts | 49 +- x-pack/plugins/ml/public/index.ts | 3 +- 17 files changed, 611 insertions(+), 421 deletions(-) diff --git a/x-pack/plugins/apm/common/service_map.ts b/x-pack/plugins/apm/common/service_map.ts index 75c1c945c5d26..2ff30a61499b6 100644 --- a/x-pack/plugins/apm/common/service_map.ts +++ b/x-pack/plugins/apm/common/service_map.ts @@ -9,7 +9,6 @@ import { ILicense } from '../../licensing/public'; import { AGENT_NAME, SERVICE_ENVIRONMENT, - SERVICE_FRAMEWORK_NAME, SERVICE_NAME, SPAN_SUBTYPE, SPAN_TYPE, @@ -19,7 +18,6 @@ import { export interface ServiceConnectionNode { [SERVICE_NAME]: string; [SERVICE_ENVIRONMENT]: string | null; - [SERVICE_FRAMEWORK_NAME]: string | null; [AGENT_NAME]: string; } export interface ExternalConnectionNode { diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index ad77434bca9f4..797145368b4b7 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -134,6 +134,11 @@ export function Cytoscape({ ); cy.remove(absentElements); cy.add(elements); + // ensure all elements get latest data properties + elements.forEach(elementDefinition => { + const el = cy.getElementById(elementDefinition.data.id as string); + el.data(elementDefinition.data); + }); cy.trigger('data'); } }, [cy, elements]); diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx index bc3434f277d1c..7e15d0116b84d 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Contents.tsx @@ -8,14 +8,23 @@ import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, - EuiTitle + EuiTitle, + EuiIconTip, + EuiHealth } from '@elastic/eui'; +import theme from '@elastic/eui/dist/eui_theme_light.json'; +import { i18n } from '@kbn/i18n'; import cytoscape from 'cytoscape'; import React from 'react'; -import { SERVICE_FRAMEWORK_NAME } from '../../../../../common/elasticsearch_fieldnames'; +import styled from 'styled-components'; +import { fontSize, px } from '../../../../style/variables'; import { Buttons } from './Buttons'; import { Info } from './Info'; import { ServiceMetricFetcher } from './ServiceMetricFetcher'; +import { MLJobLink } from '../../../shared/Links/MachineLearningLinks/MLJobLink'; +import { getSeverityColor } from '../cytoscapeOptions'; +import { asInteger } from '../../../../utils/formatters'; +import { getMetricChangeDescription } from '../../../../../../ml/public'; const popoverMinWidth = 280; @@ -27,6 +36,31 @@ interface ContentsProps { selectedNodeServiceName: string; } +const HealthStatusTitle = styled(EuiTitle)` + display: inline; + text-transform: uppercase; +`; + +const VerticallyCentered = styled.div` + display: flex; + align-items: center; +`; + +const SubduedText = styled.span` + color: ${theme.euiTextSubduedColor}; +`; + +const EnableText = styled.section` + color: ${theme.euiTextSubduedColor}; + line-height: 1.4; + font-size: ${fontSize}; + width: ${px(popoverMinWidth)}; +`; + +export const ContentLine = styled.section` + line-height: 2; +`; + // IE 11 does not handle flex properties as expected. With browser detection, // we can use regular div elements to render contents that are almost identical. // @@ -51,6 +85,37 @@ const FlexColumnGroup = (props: { const FlexColumnItem = (props: { children: React.ReactNode }) => isIE11 ?
: ; +const ANOMALY_DETECTION_TITLE = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverTitle', + { defaultMessage: 'Anomaly Detection' } +); + +const ANOMALY_DETECTION_INFO = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverInfo', + { + defaultMessage: + 'Display the health of your service by enabling the anomaly detection feature in Machine Learning.' + } +); + +const ANOMALY_DETECTION_SCORE_METRIC = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverScoreMetric', + { defaultMessage: 'Score (max.)' } +); + +const ANOMALY_DETECTION_LINK = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverLink', + { defaultMessage: 'View anomalies' } +); + +const ANOMALY_DETECTION_ENABLE_TEXT = i18n.translate( + 'xpack.apm.serviceMap.anomalyDetectionPopoverEnable', + { + defaultMessage: + 'Enable anomaly detection from the Integrations menu in the Service details view.' + } +); + export function Contents({ selectedNodeData, isService, @@ -58,7 +123,23 @@ export function Contents({ onFocusClick, selectedNodeServiceName }: ContentsProps) { - const frameworkName = selectedNodeData[SERVICE_FRAMEWORK_NAME]; + // Anomaly Detection + const severity = selectedNodeData.severity; + const maxScore = selectedNodeData.max_score; + const actualValue = selectedNodeData.actual_value; + const typicalValue = selectedNodeData.typical_value; + const jobId = selectedNodeData.job_id; + const hasAnomalyDetection = [ + severity, + maxScore, + actualValue, + typicalValue, + jobId + ].every(value => value !== undefined); + const anomalyDescription = hasAnomalyDetection + ? getMetricChangeDescription(actualValue, typicalValue).message + : null; + return ( + {isService && ( + +
+ +

{ANOMALY_DETECTION_TITLE}

+
+   + +
+ {hasAnomalyDetection ? ( + <> + + + + + + + {ANOMALY_DETECTION_SCORE_METRIC} + + + + +
+ {asInteger(maxScore)} +  ({anomalyDescription}) +
+
+
+
+ + + {ANOMALY_DETECTION_LINK} + + + + ) : ( + {ANOMALY_DETECTION_ENABLE_TEXT} + )} + +
+ )} {isService ? ( - + ) : ( )} diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx index 23e9e737be9a6..e5962afd76eb8 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/Popover.stories.tsx @@ -16,7 +16,6 @@ storiesOf('app/ServiceMap/Popover/ServiceMetricList', module) avgRequestsPerMinute={164.47222031860858} avgCpuUsage={0.32809666568309237} avgMemoryUsage={0.5504868173242986} - frameworkName="Spring" numInstances={2} isLoading={false} /> diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricFetcher.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricFetcher.tsx index 5e6412333a2e1..6f67f7a4bed7a 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricFetcher.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricFetcher.tsx @@ -11,12 +11,10 @@ import { useUrlParams } from '../../../../hooks/useUrlParams'; import { ServiceMetricList } from './ServiceMetricList'; interface ServiceMetricFetcherProps { - frameworkName?: string; serviceName: string; } export function ServiceMetricFetcher({ - frameworkName, serviceName }: ServiceMetricFetcherProps) { const { @@ -39,11 +37,5 @@ export function ServiceMetricFetcher({ ); const isLoading = status === 'loading'; - return ( - - ); + return ; } diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx index 3cee986261a68..5c28fc0a5a7d0 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/ServiceMetricList.tsx @@ -34,21 +34,20 @@ const BadgeRow = styled(EuiFlexItem)` padding-bottom: ${lightTheme.gutterTypes.gutterSmall}; `; -const ItemRow = styled('tr')` +export const ItemRow = styled('tr')` line-height: 2; `; -const ItemTitle = styled('td')` +export const ItemTitle = styled('td')` color: ${lightTheme.textColors.subdued}; padding-right: 1rem; `; -const ItemDescription = styled('td')` +export const ItemDescription = styled('td')` text-align: right; `; interface ServiceMetricListProps extends ServiceNodeMetrics { - frameworkName?: string; isLoading: boolean; } @@ -58,7 +57,6 @@ export function ServiceMetricList({ avgErrorsPerMinute, avgCpuUsage, avgMemoryUsage, - frameworkName, numInstances, isLoading }: ServiceMetricListProps) { @@ -112,7 +110,7 @@ export function ServiceMetricList({ : null } ]; - const showBadgeRow = frameworkName || numInstances > 1; + const showBadgeRow = numInstances > 1; return isLoading ? ( @@ -121,7 +119,6 @@ export function ServiceMetricList({ {showBadgeRow && ( - {frameworkName && {frameworkName}} {numInstances > 1 && ( {i18n.translate('xpack.apm.serviceMap.numInstancesMetric', { diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape-layout-test-response.json b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape-layout-test-response.json index 4b4b5c2ed802e..e55ba65bcbcb9 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape-layout-test-response.json +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscape-layout-test-response.json @@ -3,38 +3,19 @@ { "data": { "source": "apm-server", - "target": ">172.17.0.1", - "id": "apm-server~>172.17.0.1", + "target": ">elasticsearch", + "id": "apm-server~>elasticsearch", "sourceData": { - "service.environment": null, + "id": "apm-server", "service.name": "apm-server", - "agent.name": "go", - "id": "apm-server" - }, - "targetData": { - "destination.address": "172.17.0.1", - "span.subtype": "http", - "span.type": "external", - "id": ">172.17.0.1" - } - } - }, - { - "data": { - "source": "client", - "target": ">opbeans-node", - "id": "client~>opbeans-node", - "sourceData": { - "service.environment": null, - "service.name": "client", - "agent.name": "js-base", - "id": "client" + "agent.name": "go" }, "targetData": { - "destination.address": "opbeans-node", - "span.subtype": null, - "span.type": "resource", - "id": ">opbeans-node" + "span.subtype": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.type": "db", + "id": ">elasticsearch", + "label": "elasticsearch" } } }, @@ -44,135 +25,39 @@ "target": "opbeans-node", "id": "client~opbeans-node", "sourceData": { - "service.environment": null, + "id": "client", "service.name": "client", - "agent.name": "js-base", - "id": "client" + "agent.name": "rum-js" }, "targetData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" } } }, - { - "data": { - "source": "opbeans-dotnet", - "target": "opbeans-go", - "id": "opbeans-dotnet~opbeans-go", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-go", - "agent.name": "go", - "id": "opbeans-go" - }, - "bidirectional": true - } - }, - { - "data": { - "source": "opbeans-dotnet", - "target": "opbeans-java", - "id": "opbeans-dotnet~opbeans-java", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-java", - "agent.name": "java", - "id": "opbeans-java" - }, - "bidirectional": true - } - }, - { - "data": { - "source": "opbeans-dotnet", - "target": "opbeans-node", - "id": "opbeans-dotnet~opbeans-node", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-node", - "agent.name": "nodejs", - "id": "opbeans-node" - }, - "bidirectional": true - } - }, - { - "data": { - "source": "opbeans-dotnet", - "target": "opbeans-python", - "id": "opbeans-dotnet~opbeans-python", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-python", - "agent.name": "python", - "id": "opbeans-python" - }, - "bidirectional": true - } - }, - { - "data": { - "source": "opbeans-dotnet", - "target": "opbeans-ruby", - "id": "opbeans-dotnet~opbeans-ruby", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-ruby", - "agent.name": "ruby", - "id": "opbeans-ruby" - }, - "bidirectional": true - } - }, { "data": { "source": "opbeans-go", - "target": ">postgres", - "id": "opbeans-go~>postgres", + "target": ">postgresql", + "id": "opbeans-go~>postgresql", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { - "destination.address": "postgres", "span.subtype": "postgresql", + "span.destination.service.resource": "postgresql", "span.type": "db", - "id": ">postgres" + "id": ">postgresql", + "label": "postgresql" } } }, @@ -182,18 +67,22 @@ "target": "opbeans-dotnet", "id": "opbeans-go~opbeans-dotnet", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { - "service.environment": "production", + "id": "opbeans-dotnet", "service.name": "opbeans-dotnet", "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "isInverseEdge": true + "service.framework.name": "ASP.NET Core", + "max_score": 43.63972429875661, + "severity": "minor" + } } }, { @@ -202,16 +91,21 @@ "target": "opbeans-java", "id": "opbeans-go~opbeans-java", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "bidirectional": true } @@ -222,16 +116,20 @@ "target": "opbeans-node", "id": "opbeans-go~opbeans-node", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "bidirectional": true } @@ -242,16 +140,22 @@ "target": "opbeans-python", "id": "opbeans-go~opbeans-python", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "bidirectional": true } @@ -262,16 +166,20 @@ "target": "opbeans-ruby", "id": "opbeans-go~opbeans-ruby", "sourceData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "targetData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "bidirectional": true } @@ -279,19 +187,22 @@ { "data": { "source": "opbeans-java", - "target": ">postgres", - "id": "opbeans-java~>postgres", + "target": ">postgresql", + "id": "opbeans-java~>postgresql", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { - "destination.address": "postgres", "span.subtype": "postgresql", + "span.destination.service.resource": "postgresql", "span.type": "db", - "id": ">postgres" + "id": ">postgresql", + "label": "postgresql" } } }, @@ -301,18 +212,21 @@ "target": "opbeans-dotnet", "id": "opbeans-java~opbeans-dotnet", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { - "service.environment": "production", + "id": "opbeans-dotnet", "service.name": "opbeans-dotnet", "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "isInverseEdge": true + "service.framework.name": "ASP.NET Core", + "max_score": 43.63972429875661, + "severity": "minor" + } } }, { @@ -321,16 +235,21 @@ "target": "opbeans-go", "id": "opbeans-java~opbeans-go", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "isInverseEdge": true } @@ -341,16 +260,19 @@ "target": "opbeans-node", "id": "opbeans-java~opbeans-node", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "bidirectional": true } @@ -361,16 +283,21 @@ "target": "opbeans-python", "id": "opbeans-java~opbeans-python", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "bidirectional": true } @@ -381,56 +308,43 @@ "target": "opbeans-ruby", "id": "opbeans-java~opbeans-ruby", "sourceData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "targetData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "bidirectional": true } }, - { - "data": { - "source": "opbeans-node", - "target": "opbeans-dotnet", - "id": "opbeans-node~opbeans-dotnet", - "sourceData": { - "service.environment": "production", - "service.name": "opbeans-node", - "agent.name": "nodejs", - "id": "opbeans-node" - }, - "targetData": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "isInverseEdge": true - } - }, { "data": { "source": "opbeans-node", "target": "opbeans-go", "id": "opbeans-node~opbeans-go", "sourceData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "targetData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "isInverseEdge": true } @@ -441,16 +355,19 @@ "target": "opbeans-java", "id": "opbeans-node~opbeans-java", "sourceData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "targetData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "isInverseEdge": true } @@ -461,16 +378,20 @@ "target": "opbeans-python", "id": "opbeans-node~opbeans-python", "sourceData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "targetData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "bidirectional": true } @@ -481,38 +402,113 @@ "target": "opbeans-ruby", "id": "opbeans-node~opbeans-ruby", "sourceData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "targetData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "bidirectional": true } }, + { + "data": { + "source": "opbeans-python", + "target": ">elasticsearch", + "id": "opbeans-python~>elasticsearch", + "sourceData": { + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + "agent.name": "python", + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" + }, + "targetData": { + "span.subtype": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.type": "db", + "id": ">elasticsearch", + "label": "elasticsearch" + } + } + }, + { + "data": { + "source": "opbeans-python", + "target": ">postgresql", + "id": "opbeans-python~>postgresql", + "sourceData": { + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + "agent.name": "python", + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" + }, + "targetData": { + "span.subtype": "postgresql", + "span.destination.service.resource": "postgresql", + "span.type": "db", + "id": ">postgresql", + "label": "postgresql" + } + } + }, + { + "data": { + "source": "opbeans-python", + "target": ">redis", + "id": "opbeans-python~>redis", + "sourceData": { + "id": "opbeans-python", + "service.environment": "production", + "service.name": "opbeans-python", + "agent.name": "python", + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" + }, + "targetData": { + "span.subtype": "redis", + "span.destination.service.resource": "redis", + "span.type": "db", + "id": ">redis", + "label": "redis" + } + } + }, { "data": { "source": "opbeans-python", "target": "opbeans-dotnet", "id": "opbeans-python~opbeans-dotnet", "sourceData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "targetData": { - "service.environment": "production", + "id": "opbeans-dotnet", "service.name": "opbeans-dotnet", "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "isInverseEdge": true + "service.framework.name": "ASP.NET Core", + "max_score": 43.63972429875661, + "severity": "minor" + } } }, { @@ -521,16 +517,22 @@ "target": "opbeans-go", "id": "opbeans-python~opbeans-go", "sourceData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "targetData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "isInverseEdge": true } @@ -541,16 +543,21 @@ "target": "opbeans-java", "id": "opbeans-python~opbeans-java", "sourceData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "targetData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "isInverseEdge": true } @@ -561,16 +568,20 @@ "target": "opbeans-node", "id": "opbeans-python~opbeans-node", "sourceData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "targetData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "isInverseEdge": true } @@ -581,38 +592,65 @@ "target": "opbeans-ruby", "id": "opbeans-python~opbeans-ruby", "sourceData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "targetData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "bidirectional": true } }, + { + "data": { + "source": "opbeans-ruby", + "target": ">postgresql", + "id": "opbeans-ruby~>postgresql", + "sourceData": { + "id": "opbeans-ruby", + "service.environment": "production", + "service.name": "opbeans-ruby", + "agent.name": "ruby", + "service.framework.name": "Ruby on Rails" + }, + "targetData": { + "span.subtype": "postgresql", + "span.destination.service.resource": "postgresql", + "span.type": "db", + "id": ">postgresql", + "label": "postgresql" + } + } + }, { "data": { "source": "opbeans-ruby", "target": "opbeans-dotnet", "id": "opbeans-ruby~opbeans-dotnet", "sourceData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "targetData": { - "service.environment": "production", + "id": "opbeans-dotnet", "service.name": "opbeans-dotnet", "agent.name": "dotnet", - "id": "opbeans-dotnet" - }, - "isInverseEdge": true + "service.framework.name": "ASP.NET Core", + "max_score": 43.63972429875661, + "severity": "minor" + } } }, { @@ -621,16 +659,20 @@ "target": "opbeans-go", "id": "opbeans-ruby~opbeans-go", "sourceData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "targetData": { + "id": "opbeans-go", "service.environment": "production", "service.name": "opbeans-go", "agent.name": "go", - "id": "opbeans-go" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" }, "isInverseEdge": true } @@ -641,16 +683,19 @@ "target": "opbeans-java", "id": "opbeans-ruby~opbeans-java", "sourceData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "targetData": { + "id": "opbeans-java", "service.environment": "production", "service.name": "opbeans-java", "agent.name": "java", - "id": "opbeans-java" + "max_score": 31.374423806075157, + "severity": "minor" }, "isInverseEdge": true } @@ -661,16 +706,18 @@ "target": "opbeans-node", "id": "opbeans-ruby~opbeans-node", "sourceData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "targetData": { + "id": "opbeans-node", "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "id": "opbeans-node" + "service.framework.name": "express" }, "isInverseEdge": true } @@ -681,178 +728,123 @@ "target": "opbeans-python", "id": "opbeans-ruby~opbeans-python", "sourceData": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" + "service.framework.name": "Ruby on Rails" }, "targetData": { + "id": "opbeans-python", "service.environment": "production", "service.name": "opbeans-python", "agent.name": "python", - "id": "opbeans-python" + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" }, "isInverseEdge": true } }, { "data": { - "service.environment": null, - "service.name": "client", - "agent.name": "js-base", - "id": "client" - } - }, - { - "data": { - "service.environment": "production", - "service.name": "opbeans-node", - "agent.name": "nodejs", - "id": "opbeans-node" - } - }, - { - "data": { + "id": "opbeans-java", "service.environment": "production", - "service.name": "opbeans-go", - "agent.name": "go", - "id": "opbeans-go" + "service.name": "opbeans-java", + "agent.name": "java", + "max_score": 31.374423806075157, + "severity": "minor" } }, { "data": { + "id": "opbeans-python", "service.environment": "production", - "service.name": "opbeans-java", - "agent.name": "java", - "id": "opbeans-java" + "service.name": "opbeans-python", + "agent.name": "python", + "service.framework.name": "django", + "max_score": 92.48735, + "severity": "critical" } }, { "data": { - "destination.address": "postgres", "span.subtype": "postgresql", + "span.destination.service.resource": "postgresql", "span.type": "db", - "id": ">postgres" + "id": ">postgresql", + "label": "postgresql" } }, { "data": { + "id": "opbeans-ruby", "service.environment": "production", "service.name": "opbeans-ruby", "agent.name": "ruby", - "id": "opbeans-ruby" - } - }, - { - "data": { - "service.environment": "production", - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "id": "opbeans-dotnet" + "service.framework.name": "Ruby on Rails" } }, { "data": { + "id": "opbeans-go", "service.environment": "production", - "service.name": "opbeans-python", - "agent.name": "python", - "id": "opbeans-python" - } - }, - { - "data": { - "destination.address": "opbeans-node", - "span.subtype": null, - "span.type": "resource", - "id": ">opbeans-node" - } - }, - { - "data": { - "service.environment": null, - "service.name": "apm-server", + "service.name": "opbeans-go", "agent.name": "go", - "id": "apm-server" - } - }, - { - "data": { - "destination.address": "172.17.0.1", - "span.subtype": "http", - "span.type": "external", - "id": ">172.17.0.1" + "service.framework.name": "gin", + "max_score": 92.40731, + "severity": "critical" } }, { "data": { + "id": "apm-server", "service.name": "apm-server", - "agent.name": "go", - "service.environment": null, - "service.framework.name": null, - "id": "apm-server" - } - }, - { - "data": { - "service.name": "opbeans-python", - "agent.name": "python", - "service.environment": null, - "service.framework.name": "django", - "id": "opbeans-python" + "agent.name": "go" } }, { "data": { - "service.name": "opbeans-ruby", - "agent.name": "ruby", - "service.environment": null, - "service.framework.name": "Ruby on Rails", - "id": "opbeans-ruby" + "span.subtype": "elasticsearch", + "span.destination.service.resource": "elasticsearch", + "span.type": "db", + "id": ">elasticsearch", + "label": "elasticsearch" } }, { "data": { + "id": "opbeans-node", + "service.environment": "production", "service.name": "opbeans-node", "agent.name": "nodejs", - "service.environment": null, - "service.framework.name": "express", - "id": "opbeans-node" + "service.framework.name": "express" } }, { "data": { - "service.name": "opbeans-go", - "agent.name": "go", - "service.environment": null, - "service.framework.name": "gin", - "id": "opbeans-go" - } - }, - { - "data": { - "service.name": "opbeans-java", - "agent.name": "java", - "service.environment": null, - "service.framework.name": null, - "id": "opbeans-java" + "id": "opbeans-dotnet", + "service.name": "opbeans-dotnet", + "agent.name": "dotnet", + "service.framework.name": "ASP.NET Core", + "max_score": 43.63972429875661, + "severity": "minor" } }, { "data": { - "service.name": "opbeans-dotnet", - "agent.name": "dotnet", - "service.environment": null, - "service.framework.name": "ASP.NET Core", - "id": "opbeans-dotnet" + "span.subtype": "redis", + "span.destination.service.resource": "redis", + "span.type": "db", + "id": ">redis", + "label": "redis" } }, { "data": { + "id": "client", "service.name": "client", - "agent.name": "js-base", - "service.environment": null, - "service.framework.name": null, - "id": "client" + "agent.name": "rum-js" } } ] diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts index 3bb4319d0722d..0cdc7c4eb124d 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts @@ -13,9 +13,7 @@ import { import { severity } from '../../../../common/ml_job_constants'; import { defaultIcon, iconForNode } from './icons'; -const getBorderColor = (el: cytoscape.NodeSingular) => { - const nodeSeverity = el.data('severity'); - +export const getSeverityColor = (nodeSeverity: string) => { switch (nodeSeverity) { case severity.warning: return theme.euiColorVis0; @@ -24,11 +22,20 @@ const getBorderColor = (el: cytoscape.NodeSingular) => { case severity.critical: return theme.euiColorVis9; default: - if (el.hasClass('primary') || el.selected()) { - return theme.euiColorPrimary; - } else { - return theme.euiColorMediumShade; - } + return; + } +}; + +const getBorderColor = (el: cytoscape.NodeSingular) => { + const nodeSeverity = el.data('severity'); + const severityColor = getSeverityColor(nodeSeverity); + if (severityColor) { + return severityColor; + } + if (el.hasClass('primary') || el.selected()) { + return theme.euiColorPrimary; + } else { + return theme.euiColorMediumShade; } }; diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.test.tsx b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.test.tsx index 75a247a1aae40..9065f20ae600e 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.test.tsx @@ -10,7 +10,7 @@ import { getRenderedHref } from '../../../../utils/testHelpers'; import { MLJobLink } from './MLJobLink'; describe('MLJobLink', () => { - it('should produce the correct URL', async () => { + it('should produce the correct URL with serviceName', async () => { const href = await getRenderedHref( () => ( { { search: '?rangeFrom=now/w&rangeTo=now-4h' } as Location ); + expect(href).toEqual( + `/basepath/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:true,value:'0'),time:(from:now%2Fw,to:now-4h))` + ); + }); + it('should produce the correct URL with jobId', async () => { + const href = await getRenderedHref( + () => ( + + ), + { search: '?rangeFrom=now/w&rangeTo=now-4h' } as Location + ); + expect(href).toEqual( `/basepath/app/ml#/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:true,value:'0'),time:(from:now%2Fw,to:now-4h))` ); diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.tsx index 81c5d17d491c0..b085fab2b7ed6 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLJobLink.tsx @@ -8,22 +8,33 @@ import React from 'react'; import { getMlJobId } from '../../../../../common/ml_job_constants'; import { MLLink } from './MLLink'; -interface Props { +interface PropsServiceName { serviceName: string; transactionType?: string; } +interface PropsJobId { + jobId: string; +} + +type Props = (PropsServiceName | PropsJobId) & { + external?: boolean; +}; -export const MLJobLink: React.FC = ({ - serviceName, - transactionType, - children -}) => { - const jobId = getMlJobId(serviceName, transactionType); +export const MLJobLink: React.FC = props => { + const jobId = + 'jobId' in props + ? props.jobId + : getMlJobId(props.serviceName, props.transactionType); const query = { ml: { jobIds: [jobId] } }; return ( - + ); }; diff --git a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx index 3671a0089fd6e..7b57c193d896d 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/MachineLearningLinks/MLLink.tsx @@ -22,9 +22,10 @@ interface Props { query?: MlRisonData; path?: string; children?: React.ReactNode; + external?: boolean; } -export function MLLink({ children, path = '', query = {} }: Props) { +export function MLLink({ children, path = '', query = {}, external }: Props) { const { core } = useApmPluginContext(); const location = useLocation(); @@ -41,5 +42,12 @@ export function MLLink({ children, path = '', query = {} }: Props) { hash: `${path}?_g=${rison.encode(risonQuery as RisonValue)}` }); - return ; + return ( + + ); } diff --git a/x-pack/plugins/apm/server/lib/helpers/range_filter.ts b/x-pack/plugins/apm/server/lib/helpers/range_filter.ts index 39581687f04f2..0647144a19c1d 100644 --- a/x-pack/plugins/apm/server/lib/helpers/range_filter.ts +++ b/x-pack/plugins/apm/server/lib/helpers/range_filter.ts @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -export function rangeFilter(start: number, end: number) { +export function rangeFilter( + start: number, + end: number, + timestampField = '@timestamp' +) { return { - '@timestamp': { + [timestampField]: { gte: start, lte: end, format: 'epoch_millis' diff --git a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts index 572d73e368c7a..4af8a54139204 100644 --- a/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/dedupe_connections/index.test.ts @@ -9,7 +9,6 @@ import { SPAN_DESTINATION_SERVICE_RESOURCE, SERVICE_NAME, SERVICE_ENVIRONMENT, - SERVICE_FRAMEWORK_NAME, AGENT_NAME, SPAN_TYPE, SPAN_SUBTYPE @@ -19,7 +18,6 @@ import { dedupeConnections } from './'; const nodejsService = { [SERVICE_NAME]: 'opbeans-node', [SERVICE_ENVIRONMENT]: 'production', - [SERVICE_FRAMEWORK_NAME]: null, [AGENT_NAME]: 'nodejs' }; @@ -32,7 +30,6 @@ const nodejsExternal = { const javaService = { [SERVICE_NAME]: 'opbeans-java', [SERVICE_ENVIRONMENT]: 'production', - [SERVICE_FRAMEWORK_NAME]: null, [AGENT_NAME]: 'java' }; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts index adb2c9b7cb084..7d5f0a75d2208 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map.ts @@ -7,7 +7,6 @@ import { chunk } from 'lodash'; import { AGENT_NAME, SERVICE_ENVIRONMENT, - SERVICE_FRAMEWORK_NAME, SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; import { getServicesProjection } from '../../../common/projections/services'; @@ -19,6 +18,7 @@ import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; import { addAnomaliesToServicesData } from './ml_helpers'; import { getMlIndex } from '../../../common/ml_job_constants'; +import { rangeFilter } from '../helpers/range_filter'; export interface IEnvOptions { setup: Setup & SetupTimeRange; @@ -107,11 +107,6 @@ async function getServicesData(options: IEnvOptions) { terms: { field: AGENT_NAME } - }, - service_framework_name: { - terms: { - field: SERVICE_FRAMEWORK_NAME - } } } } @@ -129,38 +124,32 @@ async function getServicesData(options: IEnvOptions) { [SERVICE_NAME]: bucket.key as string, [AGENT_NAME]: (bucket.agent_name.buckets[0]?.key as string | undefined) || '', - [SERVICE_ENVIRONMENT]: options.environment || null, - [SERVICE_FRAMEWORK_NAME]: - (bucket.service_framework_name.buckets[0]?.key as - | string - | undefined) || null + [SERVICE_ENVIRONMENT]: options.environment || null }; }) || [] ); } function getAnomaliesData(options: IEnvOptions) { - const { client } = options.setup; + const { start, end, client } = options.setup; + const rangeQuery = { range: rangeFilter(start, end, 'timestamp') }; const params = { index: getMlIndex('*'), body: { size: 0, query: { - exists: { - field: 'bucket_span' - } + bool: { filter: [{ term: { result_type: 'record' } }, rangeQuery] } }, aggs: { jobs: { - terms: { - field: 'job_id', - size: 10 - }, + terms: { field: 'job_id', size: 10 }, aggs: { - max_score: { - max: { - field: 'anomaly_score' + top_score_hits: { + top_hits: { + sort: [{ record_score: { order: 'desc' as const } }], + _source: ['job_id', 'record_score', 'typical', 'actual'], + size: 1 } } } @@ -178,7 +167,13 @@ export type ServicesResponse = PromiseReturnType; export type ServiceMapAPIResponse = PromiseReturnType; export async function getServiceMap(options: IEnvOptions) { - const [connectionData, servicesData, anomaliesData] = await Promise.all([ + const [connectionData, servicesData, anomaliesData]: [ + // explicit types to avoid TS "excessively deep" error + ConnectionsResponse, + ServicesResponse, + AnomaliesResponse + // @ts-ignore + ] = await Promise.all([ getConnectionData(options), getServicesData(options), getAnomaliesData(options) diff --git a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts index c6680ecd6375b..c80ba8dba01ea 100644 --- a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.test.ts @@ -13,14 +13,12 @@ describe('addAnomaliesToServicesData', () => { { 'service.name': 'opbeans-ruby', 'agent.name': 'ruby', - 'service.environment': null, - 'service.framework.name': 'Ruby on Rails' + 'service.environment': null }, { 'service.name': 'opbeans-java', 'agent.name': 'java', - 'service.environment': null, - 'service.framework.name': null + 'service.environment': null } ]; @@ -30,11 +28,37 @@ describe('addAnomaliesToServicesData', () => { buckets: [ { key: 'opbeans-ruby-request-high_mean_response_time', - max_score: { value: 50 } + top_score_hits: { + hits: { + hits: [ + { + _source: { + record_score: 50, + actual: [2000], + typical: [1000], + job_id: 'opbeans-ruby-request-high_mean_response_time' + } + } + ] + } + } }, { key: 'opbeans-java-request-high_mean_response_time', - max_score: { value: 100 } + top_score_hits: { + hits: { + hits: [ + { + _source: { + record_score: 100, + actual: [9000], + typical: [3000], + job_id: 'opbeans-java-request-high_mean_response_time' + } + } + ] + } + } } ] } @@ -46,17 +70,21 @@ describe('addAnomaliesToServicesData', () => { 'service.name': 'opbeans-ruby', 'agent.name': 'ruby', 'service.environment': null, - 'service.framework.name': 'Ruby on Rails', max_score: 50, - severity: 'major' + severity: 'major', + actual_value: 2000, + typical_value: 1000, + job_id: 'opbeans-ruby-request-high_mean_response_time' }, { 'service.name': 'opbeans-java', 'agent.name': 'java', 'service.environment': null, - 'service.framework.name': null, max_score: 100, - severity: 'critical' + severity: 'critical', + actual_value: 9000, + typical_value: 3000, + job_id: 'opbeans-java-request-high_mean_response_time' } ]; diff --git a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts index 26a964bfb4dd2..9789911660bd0 100644 --- a/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts +++ b/x-pack/plugins/apm/server/lib/service_map/ml_helpers.ts @@ -18,29 +18,54 @@ export function addAnomaliesToServicesData( const anomaliesMap = ( anomaliesResponse.aggregations?.jobs.buckets ?? [] ).reduce<{ - [key: string]: { max_score?: number }; + [key: string]: { + max_score?: number; + actual_value?: number; + typical_value?: number; + job_id?: string; + }; }>((previousValue, currentValue) => { const key = getMlJobServiceName(currentValue.key.toString()); + const hitSource = currentValue.top_score_hits.hits.hits[0]._source as { + record_score: number; + actual: [number]; + typical: [number]; + job_id: string; + }; + const maxScore = hitSource.record_score; + const actualValue = hitSource.actual[0]; + const typicalValue = hitSource.typical[0]; + const jobId = hitSource.job_id; + + if ((previousValue[key]?.max_score ?? 0) > maxScore) { + return previousValue; + } return { ...previousValue, [key]: { - max_score: Math.max( - previousValue[key]?.max_score ?? 0, - currentValue.max_score.value ?? 0 - ) + max_score: maxScore, + actual_value: actualValue, + typical_value: typicalValue, + job_id: jobId } }; }, {}); const servicesDataWithAnomalies = servicesData.map(service => { - const score = anomaliesMap[service[SERVICE_NAME]]?.max_score; - - return { - ...service, - max_score: score, - severity: getSeverity(score) - }; + const serviceAnomalies = anomaliesMap[service[SERVICE_NAME]]; + if (serviceAnomalies) { + const maxScore = serviceAnomalies.max_score; + return { + ...service, + max_score: maxScore, + severity: getSeverity(maxScore), + actual_value: serviceAnomalies.actual_value, + typical_value: serviceAnomalies.typical_value, + job_id: serviceAnomalies.job_id + }; + } + return service; }); return servicesDataWithAnomalies; diff --git a/x-pack/plugins/ml/public/index.ts b/x-pack/plugins/ml/public/index.ts index 8070f94a1264d..c23d042822816 100755 --- a/x-pack/plugins/ml/public/index.ts +++ b/x-pack/plugins/ml/public/index.ts @@ -13,6 +13,7 @@ import { MlSetupDependencies, MlStartDependencies, } from './plugin'; +import { getMetricChangeDescription } from './application/formatters/metric_change_description'; export const plugin: PluginInitializer< MlPluginSetup, @@ -21,4 +22,4 @@ export const plugin: PluginInitializer< MlStartDependencies > = () => new MlPlugin(); -export { MlPluginSetup, MlPluginStart }; +export { MlPluginSetup, MlPluginStart, getMetricChangeDescription }; From 33376fc368116f5a42278a231c28f4d8862a758d Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 5 May 2020 20:16:47 +0100 Subject: [PATCH 30/72] Integration of a static filesystem for the node_modules (#47998) * feat(NA): added new build step to generate a static file system for node_modules and monkey patch the bin start files to include the static file system loader on begining. * chore(NA): updated lockfile. * chore(NA): replace import to the correct static-fs files. * fix(NA): resolve for a correct static fs loader. * chore(NA): last static-fs working version. * feat(NA): changed patched entryPoints. * chore(NA): update to last static fs. * fix(NA): fix imports on webpack shims. chore(NA): added new static-fs version. * chore(NA): update to static-fs with stat and statSync. * fix(NA): vendor chunk filtering in order to include default node modules and static node modules. * refact(NA): major refact on create static modules fs task. * fix(NA): remove global from clean empty folders task. * chore(NA): change args order for deleteAll. * chore(NA): move to the new static fs * feat(NA): migrate to last apis of static fs * fix(NA): patch correct entry file. * chore(NA): last stable integration with static-fs task * chore(NA): rollback some unecessary changes * chore(NA): remove changes on sinon webpackshim * chore(NA): integrate with official static-fs version * chore(NA): integrate last thread-loader version * chore(NA): added last static-fs version * chore(NA): upgrade to last static-fs version * chore(NA): upgrade to last static-fs version 1.1.1 * chore(NA): rever static-fs version to 1.1.0 * chore(NA): upgrade static-fs to 1.1.1 * chore(NA): upgrade static-fs for last 1.2.0 version * chore(NA): update package.json * chore(NA): run apm after patched environment * chore(NA): specify rule to disable eslint for * chore(NA): remove changes in the src/apm file * chore(NA): change apm order in the dev scripts * chore(na): update static-fs versin * chore(NA): bump static fs version * chore(NA): correctly lint task file * chore(NA): move away from rimraf to del * chore(NA): bump static-fs version * chore(NA): bump static-fs version * chore(NA): bump static-fs version * chore(NA): bump static-fs version * chore(NA): bump to last static-fs version * chore(NA): apply changed according PR review feedback * chore(NA): remove changes to base optimizer * chore(NA): fix discover pattern * chore(NA): bump static-fs version * chore(NA): bump static fs to 1.6.3 * chore(NA): bump static-fs to 1.6.4 * chore(NA): bump static-fs to last version * chore(NA): bump static-fs to last version * chore(NA): bump static-fs to last version * chore(NA): bump static-fs to last version * chore(NA): bump static-fs to last version * chore(NA): bump static-fs to last version * chore(NA): bump static-fs for 1.8.3 * chore(NA): bump static-fs to 1.9.0 * chore(NA): bump static-fs to 1.9.1 * chore(NA): update to last static-fs version 1.10.0 * chore(NA): moving to @elastic/static-fs package * fix(NA): change import to the new package * chore(NA): bump elastic static-fs to 1.0.1 Co-authored-by: spalger Co-authored-by: Elastic Machine --- package.json | 1 + scripts/kibana.js | 2 +- src/cli/index.js | 2 +- src/dev/build/build_distributables.js | 2 + ...create_static_fs_with_node_modules_task.js | 64 +++++++++++++++++++ src/dev/build/tasks/index.js | 1 + yarn.lock | 5 ++ 7 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/dev/build/tasks/create_static_fs_with_node_modules_task.js diff --git a/package.json b/package.json index f822d452f9cba..30d488eb04992 100644 --- a/package.json +++ b/package.json @@ -297,6 +297,7 @@ "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", "@elastic/makelogs": "^5.0.1", + "@elastic/static-fs": "1.0.1", "@kbn/dev-utils": "1.0.0", "@kbn/es": "1.0.0", "@kbn/eslint-import-resolver-kibana": "2.0.0", diff --git a/scripts/kibana.js b/scripts/kibana.js index f5a63e6c07dd6..4da739469ffb1 100644 --- a/scripts/kibana.js +++ b/scripts/kibana.js @@ -17,6 +17,6 @@ * under the License. */ -require('../src/apm')(process.env.ELASTIC_APM_PROXY_SERVICE_NAME || 'kibana-proxy'); require('../src/setup_node_env'); +require('../src/apm')(process.env.ELASTIC_APM_PROXY_SERVICE_NAME || 'kibana-proxy'); require('../src/cli/cli'); diff --git a/src/cli/index.js b/src/cli/index.js index 45f88eaf82a5b..6dbdd800268a9 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -17,6 +17,6 @@ * under the License. */ -require('../apm')(); require('../setup_node_env'); +require('../apm')(); require('./cli'); diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js index 6c2efeebc60c3..910313ac87059 100644 --- a/src/dev/build/build_distributables.js +++ b/src/dev/build/build_distributables.js @@ -40,6 +40,7 @@ import { CreatePackageJsonTask, CreateReadmeTask, CreateRpmPackageTask, + CreateStaticFsWithNodeModulesTask, DownloadNodeBuildsTask, ExtractNodeBuildsTask, InstallDependenciesTask, @@ -126,6 +127,7 @@ export async function buildDistributables(options) { await run(CleanTypescriptTask); await run(CleanExtraFilesFromModulesTask); await run(CleanEmptyFoldersTask); + await run(CreateStaticFsWithNodeModulesTask); /** * copy generic build outputs into platform-specific build diff --git a/src/dev/build/tasks/create_static_fs_with_node_modules_task.js b/src/dev/build/tasks/create_static_fs_with_node_modules_task.js new file mode 100644 index 0000000000000..0ab296fc5c163 --- /dev/null +++ b/src/dev/build/tasks/create_static_fs_with_node_modules_task.js @@ -0,0 +1,64 @@ +/* + * 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 del from 'del'; +import globby from 'globby'; +import { resolve } from 'path'; +import { generateStaticFsVolume } from '@elastic/static-fs'; + +async function deletePathsList(list) { + for (const path of list) { + await del(path); + } +} + +async function getTopLevelNodeModulesFolders(rootDir) { + const nodeModulesFoldersForCwd = await globby(['**/node_modules', '!**/node_modules/**/*'], { + cwd: rootDir, + onlyDirectories: true, + }); + + return nodeModulesFoldersForCwd.map(folder => resolve(rootDir, folder)); +} + +export const CreateStaticFsWithNodeModulesTask = { + description: + 'Creating static filesystem with node_modules, patching entryPoints and deleting node_modules folder', + + async run(config, log, build) { + const rootDir = build.resolvePath('.'); + + // Get all the top node_modules folders + const nodeModulesFolders = await getTopLevelNodeModulesFolders(rootDir); + + // Define root entry points + const rootEntryPoints = [build.resolvePath('src/setup_node_env/index.js')]; + + // Creates the static filesystem with + // every node_module we have + const staticFsAddedPaths = await generateStaticFsVolume( + rootDir, + nodeModulesFolders, + rootEntryPoints + ); + + // Delete node_modules folder + await deletePathsList(staticFsAddedPaths); + }, +}; diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js index 8105fa8a7d5d4..0232ac4b1b5f3 100644 --- a/src/dev/build/tasks/index.js +++ b/src/dev/build/tasks/index.js @@ -25,6 +25,7 @@ export * from './create_archives_task'; export * from './create_empty_dirs_and_files_task'; export * from './create_package_json_task'; export * from './create_readme_task'; +export * from './create_static_fs_with_node_modules_task'; export * from './install_dependencies_task'; export * from './license_file_task'; export * from './nodejs'; diff --git a/yarn.lock b/yarn.lock index 7b8453ade2e8d..ea58497a3b342 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1427,6 +1427,11 @@ "@types/node-jose" "1.1.0" node-jose "1.1.0" +"@elastic/static-fs@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@elastic/static-fs/-/static-fs-1.0.1.tgz#2e084e9fc321dd4c7fb4579021ca8a6b26f3464e" + integrity sha512-Vl40Va/h0P6aDUrzgDeTabGVUb/s/W92le64E1UXTcG5927cZtTnOu0datMjr98xdr9C6RAJ3mr6zgxfox5TNw== + "@elastic/ui-ace@0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@elastic/ui-ace/-/ui-ace-0.2.3.tgz#5281aed47a79b7216c55542b0675e435692f20cd" From e864fd685eb32a40bc612b8acbad9b2d1e7bf021 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Tue, 5 May 2020 22:20:47 +0300 Subject: [PATCH 31/72] [Vis Editor] - console error on opening the Inspector from visualization editor (#65277) Closes: #65268 --- .../public/embeddable/visualize_embeddable.ts | 2 +- .../visualize/public/application/editor/editor.js | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 8ab144bc03c32..89697ecd7ed71 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -138,7 +138,7 @@ export class VisualizeEmbeddable extends Embeddable inspectorSession.close()); - // Remove that watch in case the user closes the inspector session herself. - inspectorSession.onClose.finally(removeWatch); + + if (inspectorSession) { + // Close the inspector if this scope is destroyed (e.g. because the user navigates away). + const removeWatch = $scope.$on('$destroy', () => inspectorSession.close()); + // Remove that watch in case the user closes the inspector session herself. + inspectorSession.onClose.finally(removeWatch); + } }, tooltip() { if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) { From 32be411e1f02177b4f34403465ea98e9df38ca85 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 5 May 2020 21:27:16 +0200 Subject: [PATCH 32/72] [ML] Transforms: Edit transform flyout. (#65033) Adds an option to be able to edit certain attributes of transforms. This PR adds the ability to edit the description and frequency of the transform config. The PR is prepration to add support for editing throttling in a follow up. --- .../transform/public/app/common/transform.ts | 1 + .../transform/public/app/hooks/use_api.ts | 5 + .../app/hooks/use_documentation_links.ts | 1 + .../edit_transform_flyout.tsx | 122 +++++++++++ .../edit_transform_flyout_callout.tsx | 46 +++++ .../edit_transform_flyout_form.tsx | 58 ++++++ .../edit_transform_flyout_form_text_input.tsx | 44 ++++ .../components/edit_transform_flyout/index.ts | 7 + .../use_edit_transform_flyout.test.ts | 168 ++++++++++++++++ .../use_edit_transform_flyout.ts | 190 ++++++++++++++++++ .../components/transform_list/action_edit.tsx | 65 ++++++ .../transform_list/actions.test.tsx | 3 +- .../components/transform_list/actions.tsx | 8 +- .../server/client/elasticsearch_transform.ts | 15 ++ .../transform/server/routes/api/transforms.ts | 23 +++ 15 files changed, 754 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout.tsx create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_callout.tsx create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form.tsx create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form_text_input.tsx create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/index.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.test.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.ts create mode 100644 x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx diff --git a/x-pack/plugins/transform/public/app/common/transform.ts b/x-pack/plugins/transform/public/app/common/transform.ts index 7cf7412283201..41e18ca9d1589 100644 --- a/x-pack/plugins/transform/public/app/common/transform.ts +++ b/x-pack/plugins/transform/public/app/common/transform.ts @@ -39,6 +39,7 @@ export interface CreateRequestBody extends PreviewRequestBody { dest: { index: IndexName; }; + frequency?: string; sync?: { time: { field: string; diff --git a/x-pack/plugins/transform/public/app/hooks/use_api.ts b/x-pack/plugins/transform/public/app/hooks/use_api.ts index 39341dd1add65..466575a99b2b4 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_api.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_api.ts @@ -32,6 +32,11 @@ export const useApi = () => { body: JSON.stringify(transformConfig), }); }, + updateTransform(transformId: TransformId, transformConfig: any): Promise { + return http.post(`${API_BASE_PATH}transforms/${transformId}/_update`, { + body: JSON.stringify(transformConfig), + }); + }, deleteTransforms(transformsInfo: TransformEndpointRequest[]): Promise { return http.post(`${API_BASE_PATH}delete_transforms`, { body: JSON.stringify(transformsInfo), diff --git a/x-pack/plugins/transform/public/app/hooks/use_documentation_links.ts b/x-pack/plugins/transform/public/app/hooks/use_documentation_links.ts index 7589ee0a3e935..060b228390c39 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_documentation_links.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_documentation_links.ts @@ -19,6 +19,7 @@ export const useDocumentationLinks = () => { esStackOverviewDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack-overview/${DOC_LINK_VERSION}/`, esTransform: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/${TRANSFORM_DOC_PATHS.transforms}`, esTransformPivot: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/put-transform.html#put-transform-request-body`, + esTransformUpdate: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/update-transform.html`, mlDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/`, }; }; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout.tsx new file mode 100644 index 0000000000000..a794b7e7c2143 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout.tsx @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiOverlayMask, + EuiTitle, +} from '@elastic/eui'; + +import { toMountPoint } from '../../../../../../../../../src/plugins/kibana_react/public'; + +import { getErrorMessage } from '../../../../../shared_imports'; + +import { + refreshTransformList$, + TransformPivotConfig, + REFRESH_TRANSFORM_LIST_STATE, +} from '../../../../common'; +import { ToastNotificationText } from '../../../../components'; +import { useAppDependencies, useToastNotifications } from '../../../../app_dependencies'; + +import { useApi } from '../../../../hooks/use_api'; + +import { EditTransformFlyoutCallout } from './edit_transform_flyout_callout'; +import { EditTransformFlyoutForm } from './edit_transform_flyout_form'; +import { + applyFormFieldsToTransformConfig, + useEditTransformFlyout, +} from './use_edit_transform_flyout'; + +interface EditTransformFlyoutProps { + closeFlyout: () => void; + config: TransformPivotConfig; +} + +export const EditTransformFlyout: FC = ({ closeFlyout, config }) => { + const { overlays } = useAppDependencies(); + const api = useApi(); + const toastNotifications = useToastNotifications(); + + const [state, dispatch] = useEditTransformFlyout(config); + + async function submitFormHandler() { + const requestConfig = applyFormFieldsToTransformConfig(config, state.formFields); + const transformId = config.id; + + try { + await api.updateTransform(transformId, requestConfig); + toastNotifications.addSuccess( + i18n.translate('xpack.transform.transformList.editTransformSuccessMessage', { + defaultMessage: 'Transform {transformId} updated.', + values: { transformId }, + }) + ); + closeFlyout(); + refreshTransformList$.next(REFRESH_TRANSFORM_LIST_STATE.REFRESH); + } catch (e) { + toastNotifications.addDanger({ + title: i18n.translate('xpack.transform.transformList.editTransformGenericErrorMessage', { + defaultMessage: 'An error occurred calling the API endpoint to update transforms.', + }), + text: toMountPoint(), + }); + } + } + + const isUpdateButtonDisabled = !state.isFormValid || !state.isFormTouched; + + return ( + + + + +

+ {i18n.translate('xpack.transform.transformList.editFlyoutTitle', { + defaultMessage: 'Edit {transformId}', + values: { + transformId: config.id, + }, + })} +

+
+
+ }> + + + + + + + {i18n.translate('xpack.transform.transformList.editFlyoutCancelButtonText', { + defaultMessage: 'Cancel', + })} + + + + + {i18n.translate('xpack.transform.transformList.editFlyoutUpdateButtonText', { + defaultMessage: 'Update', + })} + + + + +
+
+ ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_callout.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_callout.tsx new file mode 100644 index 0000000000000..06509360b762f --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_callout.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiLink, + EuiTextColor, +} from '@elastic/eui'; + +import { useDocumentationLinks } from '../../../../hooks/use_documentation_links'; +export const EditTransformFlyoutCallout: FC = () => { + const { esTransformUpdate } = useDocumentationLinks(); + + return ( + + + + + + + + {i18n.translate('xpack.transform.transformList.editFlyoutCalloutText', { + defaultMessage: + 'This form allows you to update a transform. The list of properties that you can update is a subset of the list that you can define when you create a transform.', + })} + + + {i18n.translate('xpack.transform.transformList.editFlyoutCalloutDocs', { + defaultMessage: 'View docs', + })} + + + + + ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form.tsx new file mode 100644 index 0000000000000..3ea009a9bb6b4 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; + +import { EuiForm } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { EditTransformFlyoutFormTextInput } from './edit_transform_flyout_form_text_input'; +import { UseEditTransformFlyoutReturnType } from './use_edit_transform_flyout'; + +interface EditTransformFlyoutFormProps { + editTransformFlyout: UseEditTransformFlyoutReturnType; +} + +export const EditTransformFlyoutForm: FC = ({ + editTransformFlyout: [state, dispatch], +}) => { + const formFields = state.formFields; + + return ( + + dispatch({ field: 'description', value })} + value={formFields.description.value} + /> + {/* + */} + dispatch({ field: 'frequency', value })} + placeholder="1m" + value={formFields.frequency.value} + /> + + ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form_text_input.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form_text_input.tsx new file mode 100644 index 0000000000000..e78a379bdad74 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/edit_transform_flyout_form_text_input.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { FC } from 'react'; + +import { EuiFieldText, EuiFormRow } from '@elastic/eui'; + +interface EditTransformFlyoutFormTextInputProps { + errorMessages: string[]; + helpText?: string; + label: string; + onChange: (value: string) => void; + placeholder?: string; + value: string; +} + +export const EditTransformFlyoutFormTextInput: FC = ({ + errorMessages, + helpText, + label, + onChange, + placeholder, + value, +}) => { + return ( + 0} + error={errorMessages} + > + 0} + value={value} + onChange={e => onChange(e.target.value)} + aria-label={label} + /> + + ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/index.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/index.ts new file mode 100644 index 0000000000000..685b1a554774e --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { EditTransformFlyout } from './edit_transform_flyout'; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.test.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.test.ts new file mode 100644 index 0000000000000..04a512cab5f1a --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.test.ts @@ -0,0 +1,168 @@ +/* + * 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 { TransformPivotConfig } from '../../../../common'; + +import { + applyFormFieldsToTransformConfig, + formReducerFactory, + frequencyValidator, + getDefaultState, +} from './use_edit_transform_flyout'; + +const getTransformConfigMock = (): TransformPivotConfig => ({ + id: 'the-transform-id', + source: { + index: ['the-transform-source-index'], + query: { + match_all: {}, + }, + }, + dest: { + index: 'the-transform-destination-index', + }, + pivot: { + group_by: { + airline: { + terms: { + field: 'airline', + }, + }, + }, + aggregations: { + 'responsetime.avg': { + avg: { + field: 'responsetime', + }, + }, + }, + }, + description: 'the-description', +}); + +const getDescriptionFieldMock = (value = '') => ({ + isOptional: true, + value, + errorMessages: [], + validator: 'string', +}); + +const getFrequencyFieldMock = (value = '') => ({ + isOptional: true, + value, + errorMessages: [], + validator: 'frequency', +}); + +describe('Transform: applyFormFieldsToTransformConfig()', () => { + test('should exclude unchanged form fields', () => { + const transformConfigMock = getTransformConfigMock(); + + const updateConfig = applyFormFieldsToTransformConfig(transformConfigMock, { + description: getDescriptionFieldMock(transformConfigMock.description), + frequency: getFrequencyFieldMock(), + }); + + // This case will return an empty object. In the actual UI, this case should not happen + // because the Update-Button will be disabled when no form field was changed. + expect(Object.keys(updateConfig)).toHaveLength(0); + expect(updateConfig.description).toBe(undefined); + expect(updateConfig.frequency).toBe(undefined); + }); + + test('should include previously nonexisting attributes', () => { + const transformConfigMock = getTransformConfigMock(); + delete transformConfigMock.description; + delete transformConfigMock.frequency; + + const updateConfig = applyFormFieldsToTransformConfig(transformConfigMock, { + description: getDescriptionFieldMock('the-new-description'), + frequency: getFrequencyFieldMock(undefined), + }); + + expect(Object.keys(updateConfig)).toHaveLength(1); + expect(updateConfig.description).toBe('the-new-description'); + expect(updateConfig.frequency).toBe(undefined); + }); + + test('should only include changed form fields', () => { + const transformConfigMock = getTransformConfigMock(); + const updateConfig = applyFormFieldsToTransformConfig(transformConfigMock, { + description: getDescriptionFieldMock('the-updated-description'), + frequency: getFrequencyFieldMock(), + }); + + expect(Object.keys(updateConfig)).toHaveLength(1); + expect(updateConfig.description).toBe('the-updated-description'); + expect(updateConfig.frequency).toBe(undefined); + }); +}); + +describe('Transform: formReducerFactory()', () => { + test('field updates should trigger form validation', () => { + const transformConfigMock = getTransformConfigMock(); + const reducer = formReducerFactory(transformConfigMock); + + const state1 = reducer(getDefaultState(transformConfigMock), { + field: 'description', + value: 'the-updated-description', + }); + + expect(state1.isFormTouched).toBe(true); + expect(state1.isFormValid).toBe(true); + + const state2 = reducer(state1, { + field: 'description', + value: transformConfigMock.description as string, + }); + + expect(state2.isFormTouched).toBe(false); + expect(state2.isFormValid).toBe(true); + + const state3 = reducer(state2, { + field: 'frequency', + value: 'the-invalid-value', + }); + + expect(state3.isFormTouched).toBe(true); + expect(state3.isFormValid).toBe(false); + expect(state3.formFields.frequency.errorMessages).toStrictEqual([ + 'The frequency value is not valid.', + ]); + }); +}); + +describe('Transform: frequencyValidator()', () => { + test('it should only allow values between 1s and 1h', () => { + // frequencyValidator() returns an array of error messages so + // an array with a length of 0 means a successful validation. + + // invalid + expect(frequencyValidator(0)).toHaveLength(1); + expect(frequencyValidator('0')).toHaveLength(1); + expect(frequencyValidator('0s')).toHaveLength(1); + expect(frequencyValidator(1)).toHaveLength(1); + expect(frequencyValidator('1')).toHaveLength(1); + expect(frequencyValidator('1ms')).toHaveLength(1); + expect(frequencyValidator('1d')).toHaveLength(1); + expect(frequencyValidator('60s')).toHaveLength(1); + expect(frequencyValidator('60m')).toHaveLength(1); + expect(frequencyValidator('60h')).toHaveLength(1); + expect(frequencyValidator('2h')).toHaveLength(1); + expect(frequencyValidator('h2')).toHaveLength(1); + expect(frequencyValidator('2h2')).toHaveLength(1); + expect(frequencyValidator('h2h')).toHaveLength(1); + + // valid + expect(frequencyValidator('1s')).toHaveLength(0); + expect(frequencyValidator('1m')).toHaveLength(0); + expect(frequencyValidator('1h')).toHaveLength(0); + expect(frequencyValidator('10s')).toHaveLength(0); + expect(frequencyValidator('10m')).toHaveLength(0); + expect(frequencyValidator('59s')).toHaveLength(0); + expect(frequencyValidator('59m')).toHaveLength(0); + }); +}); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.ts b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.ts new file mode 100644 index 0000000000000..8c4af7ac252f7 --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/edit_transform_flyout/use_edit_transform_flyout.ts @@ -0,0 +1,190 @@ +/* + * 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 { isEqual } from 'lodash'; +import { useReducer } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { TransformPivotConfig } from '../../../../common'; + +const stringNotValidErrorMessage = i18n.translate( + 'xpack.transform.transformList.editFlyoutFormStringNotValidErrorMessage', + { + defaultMessage: 'Value needs to be of type string.', + } +); + +type Validator = (arg: any) => string[]; + +// The way the current form is set up, +// this validator is just a sanity check, +// it should never trigger an error. +const stringValidator: Validator = arg => + typeof arg === 'string' ? [] : [stringNotValidErrorMessage]; + +const frequencyNotValidErrorMessage = i18n.translate( + 'xpack.transform.transformList.editFlyoutFormFrequencyNotValidErrorMessage', + { + defaultMessage: 'The frequency value is not valid.', + } +); + +// Only allow frequencies in the form of 1s/1h etc. +export const frequencyValidator: Validator = arg => { + if (typeof arg !== 'string' || arg === null) { + return [stringNotValidErrorMessage]; + } + + // split string by groups of numbers and letters + const regexStr = arg.match(/[a-z]+|[^a-z]+/gi); + + return ( + // only valid if one group of numbers and one group of letters + regexStr !== null && + regexStr.length === 2 && + // only valid if time unit is one of s/m/h + ['s', 'm', 'h'].includes(regexStr[1]) && + // only valid if number is between 1 and 59 + parseInt(regexStr[0], 10) > 0 && + parseInt(regexStr[0], 10) < 60 && + // if time unit is 'h' then number must not be higher than 1 + !(parseInt(regexStr[0], 10) > 1 && regexStr[1] === 'h') + ? [] + : [frequencyNotValidErrorMessage] + ); +}; + +interface Validate { + [key: string]: Validator; +} + +const validate: Validate = { + string: stringValidator, + frequency: frequencyValidator, +}; + +interface Field { + errorMessages: string[]; + isOptional: boolean; + validator: keyof typeof validate; + value: string; +} + +const defaultField: Field = { + errorMessages: [], + isOptional: true, + validator: 'string', + value: '', +}; + +interface EditTransformFlyoutFieldsState { + [key: string]: Field; + description: Field; + frequency: Field; +} + +export interface EditTransformFlyoutState { + formFields: EditTransformFlyoutFieldsState; + isFormTouched: boolean; + isFormValid: boolean; +} + +// This is not a redux type action, +// since for now we only have one action type. +interface Action { + field: keyof EditTransformFlyoutFieldsState; + value: string; +} + +// Some attributes can have a value of `null` to trigger +// a reset to the default value. +interface UpdateTransformPivotConfig { + description: string; + frequency: string; +} + +// Takes in the form configuration and returns a +// request object suitable to be sent to the +// transform update API endpoint. +export const applyFormFieldsToTransformConfig = ( + config: TransformPivotConfig, + { description, frequency }: EditTransformFlyoutFieldsState +): Partial => { + const updateConfig: Partial = {}; + + // set the values only if they changed from the default + // and actually differ from the previous value. + if ( + !(config.frequency === undefined && frequency.value === '') && + config.frequency !== frequency.value + ) { + updateConfig.frequency = frequency.value; + } + + if ( + !(config.description === undefined && description.value === '') && + config.description !== description.value + ) { + updateConfig.description = description.value; + } + + return updateConfig; +}; + +// Takes in a transform configuration and returns +// the default state to populate the form. +export const getDefaultState = (config: TransformPivotConfig): EditTransformFlyoutState => ({ + formFields: { + description: { ...defaultField, value: config?.description ?? '' }, + frequency: { ...defaultField, value: config?.frequency ?? '', validator: 'frequency' }, + }, + isFormTouched: false, + isFormValid: true, +}); + +// Checks each form field for error messages to return +// if the overall form is valid or not. +const isFormValid = (fieldsState: EditTransformFlyoutFieldsState) => + Object.keys(fieldsState).reduce((p, c) => p && fieldsState[c].errorMessages.length === 0, true); + +// Updates a form field with its new value, +// runs validation and populates +// `errorMessages` if any errors occur. +const formFieldReducer = (state: Field, value: string): Field => { + return { + ...state, + errorMessages: state.isOptional && value.length === 0 ? [] : validate[state.validator](value), + value, + }; +}; + +// Main form reducer triggers +// - `formFieldReducer` to update the actions field +// - compares the most recent state against the original one to update `isFormTouched` +// - sets `isFormValid` to have a flag if any of the form fields contains an error. +export const formReducerFactory = (config: TransformPivotConfig) => { + const defaultState = getDefaultState(config); + return (state: EditTransformFlyoutState, { field, value }: Action): EditTransformFlyoutState => { + const formFields = { + ...state.formFields, + [field]: formFieldReducer(state.formFields[field], value), + }; + + return { + ...state, + formFields, + isFormTouched: !isEqual(defaultState.formFields, formFields), + isFormValid: isFormValid(formFields), + }; + }; +}; + +export const useEditTransformFlyout = (config: TransformPivotConfig) => { + return useReducer(formReducerFactory(config), getDefaultState(config)); +}; + +export type UseEditTransformFlyoutReturnType = ReturnType; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx new file mode 100644 index 0000000000000..1aafbac1e1bcb --- /dev/null +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/action_edit.tsx @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useContext, useState, FC } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; + +import { TransformPivotConfig } from '../../../../common'; +import { + createCapabilityFailureMessage, + AuthorizationContext, +} from '../../../../lib/authorization'; + +import { EditTransformFlyout } from '../edit_transform_flyout'; + +interface EditActionProps { + config: TransformPivotConfig; +} + +export const EditAction: FC = ({ config }) => { + const { canCreateTransform } = useContext(AuthorizationContext).capabilities; + + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const closeFlyout = () => setIsFlyoutVisible(false); + const showFlyout = () => setIsFlyoutVisible(true); + + const buttonEditText = i18n.translate('xpack.transform.transformList.editActionName', { + defaultMessage: 'Edit', + }); + + const editButton = ( + + {buttonEditText} + + ); + + if (!canCreateTransform) { + const content = createCapabilityFailureMessage('canStartStopTransform'); + + return ( + + {editButton} + + ); + } + + return ( + <> + {editButton} + {isFlyoutVisible && } + + ); +}; diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx index e8ac2fa057ad8..aac1d8b5a3f9c 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.test.tsx @@ -12,10 +12,11 @@ describe('Transform: Transform List Actions', () => { test('getActions()', () => { const actions = getActions({ forceDisable: false }); - expect(actions).toHaveLength(3); + expect(actions).toHaveLength(4); expect(actions[0].isPrimary).toBeTruthy(); expect(typeof actions[0].render).toBe('function'); expect(typeof actions[1].render).toBe('function'); expect(typeof actions[2].render).toBe('function'); + expect(typeof actions[3].render).toBe('function'); }); }); diff --git a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx index 6a55b419e74a9..820b9e0e0d062 100644 --- a/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx +++ b/x-pack/plugins/transform/public/app/sections/transform_management/components/transform_list/actions.tsx @@ -11,9 +11,10 @@ import { TRANSFORM_STATE } from '../../../../../../common'; import { TransformListRow } from '../../../../common'; import { CloneAction } from './action_clone'; +import { DeleteAction } from './action_delete'; +import { EditAction } from './action_edit'; import { StartAction } from './action_start'; import { StopAction } from './action_stop'; -import { DeleteAction } from './action_delete'; export const getActions = ({ forceDisable }: { forceDisable: boolean }) => { return [ @@ -26,6 +27,11 @@ export const getActions = ({ forceDisable }: { forceDisable: boolean }) => { return ; }, }, + { + render: (item: TransformListRow) => { + return ; + }, + }, { render: (item: TransformListRow) => { return ; diff --git a/x-pack/plugins/transform/server/client/elasticsearch_transform.ts b/x-pack/plugins/transform/server/client/elasticsearch_transform.ts index fab9ab7f3a995..91c00f5eb5df2 100644 --- a/x-pack/plugins/transform/server/client/elasticsearch_transform.ts +++ b/x-pack/plugins/transform/server/client/elasticsearch_transform.ts @@ -65,6 +65,21 @@ export const elasticsearchJsPlugin = (Client: any, config: any, components: any) method: 'PUT', }); + transform.updateTransform = ca({ + urls: [ + { + fmt: '/_transform/<%=transformId%>/_update', + req: { + transformId: { + type: 'string', + }, + }, + }, + ], + needBody: true, + method: 'POST', + }); + transform.deleteTransform = ca({ urls: [ { diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts index bf201323a3c2f..54fbce2aa3c7f 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms.ts @@ -146,6 +146,29 @@ export function registerTransformsRoutes(routeDependencies: RouteDependencies) { return res.ok({ body: response }); }) ); + router.post( + { + path: addBasePath('transforms/{transformId}/_update'), + validate: { + ...schemaTransformId, + body: schema.maybe(schema.any()), + }, + }, + license.guardApiRoute(async (ctx, req, res) => { + const { transformId } = req.params as SchemaTransformId; + + try { + return res.ok({ + body: await ctx.transform!.dataClient.callAsCurrentUser('transform.updateTransform', { + body: req.body, + transformId, + }), + }); + } catch (e) { + return res.customError(wrapError(e)); + } + }) + ); router.post( { path: addBasePath('delete_transforms'), From 2de9346ed19bbc18cb4a26d6b3215a9756b17198 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Tue, 5 May 2020 21:30:26 +0200 Subject: [PATCH 33/72] [ML] Progress to include step. (#65305) Changes the way progress is reported to include the steps and the progress for each step. --- .../components/analytics_list/columns.tsx | 21 +++++++++---- .../analytics_list/expanded_row.tsx | 30 +++++++++++++++---- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx index 2ab8cb4a78d86..907297cf69bfc 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/columns.tsx @@ -66,15 +66,21 @@ export const getTaskStateBadge = ( export const progressColumn = { name: i18n.translate('xpack.ml.dataframe.analyticsList.progress', { - defaultMessage: 'Progress', + defaultMessage: 'Progress per Step', }), sortable: (item: DataFrameAnalyticsListRow) => getDataFrameAnalyticsProgress(item.stats), truncateText: true, render(item: DataFrameAnalyticsListRow) { - const progress = getDataFrameAnalyticsProgress(item.stats); + const totalSteps = item.stats.progress.length; + let step = 0; + let progress = 0; - if (progress === undefined) { - return null; + for (const progressStep of item.stats.progress) { + step++; + progress = progressStep.progress_percent; + if (progressStep.progress_percent < 100) { + break; + } } // For now all analytics jobs are batch jobs. @@ -98,6 +104,11 @@ export const progressColumn = { {`${progress}%`} + + + {step}/{totalSteps} + + )} {!isBatchTransform && ( @@ -118,7 +129,7 @@ export const progressColumn = {
); }, - width: '100px', + width: '130px', 'data-test-subj': 'mlAnalyticsTableColumnProgress', }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx index 43ef6b36c3972..adb6822c524ab 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_list/expanded_row.tsx @@ -171,17 +171,35 @@ export const ExpandedRow: FC = ({ item }) => { position: 'left', }; + const totalSteps = item.stats.progress.length; + let step = 0; + for (const progressStep of item.stats.progress) { + step++; + if (progressStep.progress_percent < 100) { + break; + } + } + const progress: SectionConfig = { title: i18n.translate( 'xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.progress', { defaultMessage: 'Progress' } ), - items: item.stats.progress.map(s => { - return { - title: s.phase, - description: , - }; - }), + items: [ + { + title: i18n.translate( + 'xpack.ml.dataframe.analyticsList.expandedRow.tabs.jobSettings.step', + { defaultMessage: 'Step' } + ), + description: `${step}/${totalSteps}`, + }, + ...item.stats.progress.map(s => { + return { + title: s.phase, + description: , + }; + }), + ], position: 'left', }; From 943f8b9df12610d23682057ce318993cc59fdda3 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 5 May 2020 20:44:52 +0100 Subject: [PATCH 34/72] [ML] Fix packetbeat module query (#65241) --- .../siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json index c5938aa200cd4..5986c326ea80f 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/siem_packetbeat/ml/datafeed_packetbeat_rare_user_agent.json @@ -7,7 +7,7 @@ "query": { "bool": { "filter": [ - {"term": {"event.dataset": "dns"}}, + {"term": {"event.dataset": "http"}}, {"term": {"agent.type": "packetbeat"}} ], "must_not": [ From 7cd44e02b89094e8442d073605abad2e43209ba4 Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Tue, 5 May 2020 14:52:45 -0500 Subject: [PATCH 35/72] [SIEM][Detections] ML services refactor (#65187) * Use generic type for our cluster call Our callCluster function is currently an ML client being scoped by alerting. * Use the ML client in our anomaly query This will allow us to refactor getAnomalies to use ML services. * Use ml-provided services to query for anomalies This gets us a free license check from ML. In the future, it will also check user privileges. * Add unit tests for our ML query function This is going to be touched in the near future for lists. * Retrieve job summary info as the alerting user This will ensure the proper permissions checks when retrieving this information. * Remove TODO about ML error condition If the service call fails on e.g. a license check, an error will be thrown and it will be recorded as a rule failure. --- .../signals/find_ml_signals.ts | 31 ++++-- .../signals/signal_rule_alert_type.ts | 18 ++- .../server/lib/machine_learning/index.test.ts | 104 ++++++++++++++++++ .../siem/server/lib/machine_learning/index.ts | 9 +- 4 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/siem/server/lib/machine_learning/index.test.ts diff --git a/x-pack/plugins/siem/server/lib/detection_engine/signals/find_ml_signals.ts b/x-pack/plugins/siem/server/lib/detection_engine/signals/find_ml_signals.ts index 8ac5a6cde39cc..342976f3fd0fc 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/signals/find_ml_signals.ts +++ b/x-pack/plugins/siem/server/lib/detection_engine/signals/find_ml_signals.ts @@ -6,24 +6,35 @@ import dateMath from '@elastic/datemath'; -import { AlertServices } from '../../../../../alerting/server'; - +import { APICaller, KibanaRequest } from '../../../../../../../src/core/server'; +import { MlPluginSetup } from '../../../../../ml/server'; import { getAnomalies } from '../../machine_learning'; -export const findMlSignals = async ( - jobId: string, - anomalyThreshold: number, - from: string, - to: string, - callCluster: AlertServices['callCluster'] -) => { +export const findMlSignals = async ({ + ml, + callCluster, + request, + jobId, + anomalyThreshold, + from, + to, +}: { + ml: MlPluginSetup; + callCluster: APICaller; + request: KibanaRequest; + jobId: string; + anomalyThreshold: number; + from: string; + to: string; +}) => { + const { mlSearch } = ml.mlSystemProvider(callCluster, request); const params = { jobIds: [jobId], threshold: anomalyThreshold, earliestMs: dateMath.parse(from)?.valueOf() ?? 0, latestMs: dateMath.parse(to)?.valueOf() ?? 0, }; - const relevantAnomalies = await getAnomalies(params, callCluster); + const relevantAnomalies = await getAnomalies(params, mlSearch); return relevantAnomalies; }; diff --git a/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 137603741dc8f..ca259b3581720 100644 --- a/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/siem/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -5,7 +5,7 @@ */ import { performance } from 'perf_hooks'; -import { Logger } from 'src/core/server'; +import { Logger, KibanaRequest } from 'src/core/server'; import { SIGNALS_ID, DEFAULT_SEARCH_AFTER_PAGE_SIZE } from '../../../../common/constants'; import { isJobStarted, isMlRule } from '../../../../common/detection_engine/ml_helpers'; @@ -138,8 +138,9 @@ export const signalRulesAlertType = ({ ); } + const scopedMlCallCluster = services.getScopedCallCluster(ml.mlClient); const summaryJobs = await ml - .jobServiceProvider(ml.mlClient.callAsInternalUser) + .jobServiceProvider(scopedMlCallCluster) .jobsSummary([machineLearningJobId]); const jobSummary = summaryJobs.find(job => job.id === machineLearningJobId); @@ -155,13 +156,18 @@ export const signalRulesAlertType = ({ await ruleStatusService.error(errorMessage); } - const anomalyResults = await findMlSignals( - machineLearningJobId, + const anomalyResults = await findMlSignals({ + ml, + callCluster: scopedMlCallCluster, + // This is needed to satisfy the ML Services API, but can be empty as it is + // currently unused by the mlSearch function. + request: ({} as unknown) as KibanaRequest, + jobId: machineLearningJobId, anomalyThreshold, from, to, - services.callCluster - ); + }); + const anomalyCount = anomalyResults.hits.hits.length; if (anomalyCount) { logger.info(buildRuleMessage(`Found ${anomalyCount} signals from ML anomalies.`)); diff --git a/x-pack/plugins/siem/server/lib/machine_learning/index.test.ts b/x-pack/plugins/siem/server/lib/machine_learning/index.test.ts new file mode 100644 index 0000000000000..35a080f5ade76 --- /dev/null +++ b/x-pack/plugins/siem/server/lib/machine_learning/index.test.ts @@ -0,0 +1,104 @@ +/* + * 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 { getAnomalies, AnomaliesSearchParams } from '.'; + +const getFiltersFromMock = (mock: jest.Mock) => { + const [[searchParams]] = mock.mock.calls; + return searchParams.body.query.bool.filter; +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const getBoolCriteriaFromFilters = (filters: any[]) => filters[1].bool.must; + +describe('getAnomalies', () => { + let searchParams: AnomaliesSearchParams; + + beforeEach(() => { + searchParams = { + jobIds: ['jobId1'], + threshold: 5, + earliestMs: 1588517231429, + latestMs: 1588617231429, + }; + }); + + it('calls the provided mlSearch function', () => { + const mockMlSearch = jest.fn(); + getAnomalies(searchParams, mockMlSearch); + + expect(mockMlSearch).toHaveBeenCalled(); + }); + + it('passes anomalyThreshold as part of the query', () => { + const mockMlSearch = jest.fn(); + getAnomalies(searchParams, mockMlSearch); + const filters = getFiltersFromMock(mockMlSearch); + const criteria = getBoolCriteriaFromFilters(filters); + + expect(criteria).toEqual( + expect.arrayContaining([{ range: { record_score: { gte: searchParams.threshold } } }]) + ); + }); + + it('passes time range as part of the query', () => { + const mockMlSearch = jest.fn(); + getAnomalies(searchParams, mockMlSearch); + const filters = getFiltersFromMock(mockMlSearch); + const criteria = getBoolCriteriaFromFilters(filters); + + expect(criteria).toEqual( + expect.arrayContaining([ + { + range: { + timestamp: { + gte: searchParams.earliestMs, + lte: searchParams.latestMs, + format: 'epoch_millis', + }, + }, + }, + ]) + ); + }); + + it('passes a single jobId as part of the query', () => { + const mockMlSearch = jest.fn(); + getAnomalies(searchParams, mockMlSearch); + const filters = getFiltersFromMock(mockMlSearch); + const criteria = getBoolCriteriaFromFilters(filters); + + expect(criteria).toEqual( + expect.arrayContaining([ + { + query_string: { + analyze_wildcard: false, + query: 'job_id:jobId1', + }, + }, + ]) + ); + }); + + it('passes multiple jobIds as part of the query', () => { + const mockMlSearch = jest.fn(); + searchParams.jobIds = ['jobId1', 'jobId2']; + getAnomalies(searchParams, mockMlSearch); + const filters = getFiltersFromMock(mockMlSearch); + const criteria = getBoolCriteriaFromFilters(filters); + + expect(criteria).toEqual( + expect.arrayContaining([ + { + query_string: { + analyze_wildcard: false, + query: 'job_id:jobId1 OR job_id:jobId2', + }, + }, + ]) + ); + }); +}); diff --git a/x-pack/plugins/siem/server/lib/machine_learning/index.ts b/x-pack/plugins/siem/server/lib/machine_learning/index.ts index 35789b5e202e2..eb09fdde3cce3 100644 --- a/x-pack/plugins/siem/server/lib/machine_learning/index.ts +++ b/x-pack/plugins/siem/server/lib/machine_learning/index.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SearchResponse } from 'elasticsearch'; +import { SearchResponse, SearchParams } from 'elasticsearch'; -import { AlertServices } from '../../../../alerting/server'; import { AnomalyRecordDoc as Anomaly } from '../../../../ml/common/types/anomalies'; export { Anomaly }; export type AnomalyResults = SearchResponse; +type MlSearch = (searchParams: SearchParams) => Promise>; export interface AnomaliesSearchParams { jobIds: string[]; @@ -22,12 +22,11 @@ export interface AnomaliesSearchParams { export const getAnomalies = async ( params: AnomaliesSearchParams, - callCluster: AlertServices['callCluster'] + mlSearch: MlSearch ): Promise => { const boolCriteria = buildCriteria(params); - return callCluster('search', { - index: '.ml-anomalies-*', + return mlSearch({ size: params.maxRecords || 100, body: { query: { From e5d7bb6e9a28483481659fed53610231d1f72d7c Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Tue, 5 May 2020 15:59:32 -0400 Subject: [PATCH 36/72] [Lens] Pie and treemap charts (#55477) * [Lens] Add pie and treemap visualizations * Fix types * Update to new platform * Support 2-layer treemap and legends, dark mode * Significant restructuring of code * Upgrade to latest charts library * Commit yarn.lock * chore: update elastic-charts * fix types after merge master * Add settings panel and merge visualizations * Fix tests * build: upgrade @elastic/charts to 19.0.0 * refactor: onBrushEnd breaking changes * fix: missing onBrushEnd argument changes * More updates * Fix XY rendering issue when all dates are empty * Fix bugs and tests * Use shared services location * Fix bug in XY chart * fix: update ech to 19.1.1 * fix: lens onBrushEnd breaking changes * Change how pie/treemap settings work * [Design] Fix up settings panel * [Design] Update partition chart config styles * fix eslint * Fix legend issues in pie and XY, add some tests * update to 19.1.2 * Fix text color for treemap * Fix chart switch bug * Fix suggestions Co-authored-by: Marta Bondyra Co-authored-by: Elastic Machine Co-authored-by: Marco Vettorello Co-authored-by: cchaos --- .../lens/public/assets/chart_donut.svg | 4 + .../plugins/lens/public/assets/chart_pie.svg | 4 + .../lens/public/assets/chart_treemap.svg | 5 + .../datatable_visualization/visualization.tsx | 4 +- .../config_panel/chart_switch.test.tsx | 72 ++- .../config_panel/chart_switch.tsx | 5 +- .../config_panel/layer_settings.tsx | 24 +- .../editor_frame/editor_frame.test.tsx | 1 + .../indexpattern.test.ts | 6 +- .../indexpattern_datasource/to_expression.ts | 28 +- .../metric_suggestions.test.ts | 2 +- .../metric_suggestions.ts | 2 +- .../public/pie_visualization/constants.ts | 36 ++ .../lens/public/pie_visualization/index.ts | 53 ++ .../pie_visualization/pie_visualization.tsx | 215 ++++++++ .../pie_visualization/register_expression.tsx | 130 +++++ .../render_function.test.tsx | 113 ++++ .../pie_visualization/render_function.tsx | 259 +++++++++ .../pie_visualization/render_helpers.test.ts | 183 ++++++ .../pie_visualization/render_helpers.ts | 49 ++ .../pie_visualization/settings_widget.scss | 3 + .../pie_visualization/settings_widget.tsx | 212 +++++++ .../pie_visualization/suggestions.test.ts | 522 ++++++++++++++++++ .../public/pie_visualization/suggestions.ts | 137 +++++ .../public/pie_visualization/to_expression.ts | 54 ++ .../lens/public/pie_visualization/types.ts | 42 ++ .../pie_visualization/visualization.scss | 4 + x-pack/plugins/lens/public/plugin.ts | 5 + .../xy_visualization/xy_expression.test.tsx | 130 +++++ .../public/xy_visualization/xy_expression.tsx | 48 +- .../xy_visualization/xy_suggestions.test.ts | 97 +++- .../public/xy_visualization/xy_suggestions.ts | 34 +- 32 files changed, 2393 insertions(+), 90 deletions(-) create mode 100644 x-pack/plugins/lens/public/assets/chart_donut.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_pie.svg create mode 100644 x-pack/plugins/lens/public/assets/chart_treemap.svg create mode 100644 x-pack/plugins/lens/public/pie_visualization/constants.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/index.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx create mode 100644 x-pack/plugins/lens/public/pie_visualization/register_expression.tsx create mode 100644 x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx create mode 100644 x-pack/plugins/lens/public/pie_visualization/render_function.tsx create mode 100644 x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/render_helpers.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/settings_widget.scss create mode 100644 x-pack/plugins/lens/public/pie_visualization/settings_widget.tsx create mode 100644 x-pack/plugins/lens/public/pie_visualization/suggestions.test.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/suggestions.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/to_expression.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/types.ts create mode 100644 x-pack/plugins/lens/public/pie_visualization/visualization.scss diff --git a/x-pack/plugins/lens/public/assets/chart_donut.svg b/x-pack/plugins/lens/public/assets/chart_donut.svg new file mode 100644 index 0000000000000..5e0d8b7ea83bf --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_donut.svg @@ -0,0 +1,4 @@ + + + + diff --git a/x-pack/plugins/lens/public/assets/chart_pie.svg b/x-pack/plugins/lens/public/assets/chart_pie.svg new file mode 100644 index 0000000000000..22faaf5d97661 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_pie.svg @@ -0,0 +1,4 @@ + + + + diff --git a/x-pack/plugins/lens/public/assets/chart_treemap.svg b/x-pack/plugins/lens/public/assets/chart_treemap.svg new file mode 100644 index 0000000000000..b0ee04d02b2a6 --- /dev/null +++ b/x-pack/plugins/lens/public/assets/chart_treemap.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx index 21bbcce68bf36..ed0512ba220eb 100644 --- a/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx +++ b/x-pack/plugins/lens/public/datatable_visualization/visualization.tsx @@ -115,8 +115,8 @@ export const datatableVisualization: Visualization< return [ { title, - // table with >= 10 columns will have a score of 0.6, fewer columns reduce score - score: (Math.min(table.columns.length, 10) / 10) * 0.6, + // table with >= 10 columns will have a score of 0.4, fewer columns reduce score + score: (Math.min(table.columns.length, 10) / 10) * 0.4, state: { layers: [ { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.test.tsx index c8d8064e60e38..157a871e202f7 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.test.tsx @@ -22,10 +22,11 @@ describe('chart_switch', () => { return { ...createMockVisualization(), id, + getVisualizationTypeId: jest.fn(_state => id), visualizationTypes: [ { icon: 'empty', - id: `sub${id}`, + id, label: `Label ${id}`, }, ], @@ -51,6 +52,7 @@ describe('chart_switch', () => { visB: generateVisualization('visB'), visC: { ...generateVisualization('visC'), + initialize: jest.fn((_frame, state) => state ?? { type: 'subvisC1' }), visualizationTypes: [ { icon: 'empty', @@ -68,15 +70,23 @@ describe('chart_switch', () => { label: 'C3', }, ], + getVisualizationTypeId: jest.fn(state => state.type), getSuggestions: jest.fn(options => { if (options.subVisualizationId === 'subvisC2') { return []; } + // Multiple suggestions need to be filtered return [ + { + score: 1, + title: 'Primary suggestion', + state: { type: 'subvisC3' }, + previewIcon: 'empty', + }, { score: 1, title: '', - state: `suggestion`, + state: { type: 'subvisC1', notPrimary: true }, previewIcon: 'empty', }, ]; @@ -162,7 +172,7 @@ describe('chart_switch', () => { const component = mount( { /> ); - switchTo('subvisB', component); + switchTo('visB', component); expect(dispatch).toHaveBeenCalledWith({ initialState: 'suggestion visB', @@ -201,7 +211,7 @@ describe('chart_switch', () => { /> ); - switchTo('subvisB', component); + switchTo('visB', component); expect(frame.removeLayers).toHaveBeenCalledWith(['a']); @@ -265,7 +275,7 @@ describe('chart_switch', () => { /> ); - expect(getMenuItem('subvisB', component).prop('betaBadgeIconType')).toEqual('alert'); + expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toEqual('alert'); }); it('should indicate data loss if not all layers will be used', () => { @@ -285,7 +295,7 @@ describe('chart_switch', () => { /> ); - expect(getMenuItem('subvisB', component).prop('betaBadgeIconType')).toEqual('alert'); + expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toEqual('alert'); }); it('should indicate data loss if no data will be used', () => { @@ -306,7 +316,7 @@ describe('chart_switch', () => { /> ); - expect(getMenuItem('subvisB', component).prop('betaBadgeIconType')).toEqual('alert'); + expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toEqual('alert'); }); it('should not indicate data loss if there is no data', () => { @@ -328,7 +338,7 @@ describe('chart_switch', () => { /> ); - expect(getMenuItem('subvisB', component).prop('betaBadgeIconType')).toBeUndefined(); + expect(getMenuItem('visB', component).prop('betaBadgeIconType')).toBeUndefined(); }); it('should not show a warning when the subvisualization is the same', () => { @@ -336,14 +346,14 @@ describe('chart_switch', () => { const frame = mockFrame(['a', 'b', 'c']); const visualizations = mockVisualizations(); visualizations.visC.getVisualizationTypeId.mockReturnValue('subvisC2'); - const switchVisualizationType = jest.fn(() => 'therebedragons'); + const switchVisualizationType = jest.fn(() => ({ type: 'subvisC1' })); visualizations.visC.switchVisualizationType = switchVisualizationType; const component = mount( { /> ); - switchTo('subvisB', component); + switchTo('visB', component); expect(frame.removeLayers).toHaveBeenCalledTimes(1); expect(frame.removeLayers).toHaveBeenCalledWith(['a', 'b', 'c']); @@ -403,7 +413,7 @@ describe('chart_switch', () => { const component = mount( { ); switchTo('subvisC3', component); - expect(switchVisualizationType).toHaveBeenCalledWith('subvisC3', 'suggestion'); + expect(switchVisualizationType).toHaveBeenCalledWith('subvisC3', { type: 'subvisC3' }); expect(dispatch).toHaveBeenCalledWith( expect.objectContaining({ type: 'SWITCH_VISUALIZATION', @@ -471,7 +481,7 @@ describe('chart_switch', () => { /> ); - switchTo('subvisB', component); + switchTo('visB', component); expect(dispatch).toHaveBeenCalledWith({ type: 'SWITCH_VISUALIZATION', @@ -503,10 +513,10 @@ describe('chart_switch', () => { /> ); - switchTo('subvisB', component); + switchTo('visB', component); expect(dispatch).toHaveBeenCalledWith({ - initialState: 'suggestion visB subvisB', + initialState: 'suggestion visB visB', newVisualizationId: 'visB', type: 'SWITCH_VISUALIZATION', datasourceId: 'testDatasource', @@ -514,6 +524,32 @@ describe('chart_switch', () => { }); }); + it('should use the suggestion that matches the subtype', () => { + const dispatch = jest.fn(); + const visualizations = mockVisualizations(); + const switchVisualizationType = jest.fn(); + + visualizations.visC.switchVisualizationType = switchVisualizationType; + + const component = mount( + + ); + + switchTo('subvisC1', component); + expect(switchVisualizationType).toHaveBeenCalledWith('subvisC1', { + type: 'subvisC1', + notPrimary: true, + }); + }); + it('should show all visualization types', () => { const component = mount( { showFlyout(component); - const allDisplayed = ['subvisA', 'subvisB', 'subvisC1', 'subvisC2'].every( + const allDisplayed = ['visA', 'visB', 'subvisC1', 'subvisC2', 'subvisC3'].every( subType => component.find(`[data-test-subj="lnsChartSwitchPopover_${subType}"]`).length > 0 ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.tsx index d73f83e75c0e4..81eb82dfdbab4 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch.tsx @@ -272,7 +272,10 @@ function getTopSuggestion( }).filter(suggestion => { // don't use extended versions of current data table on switching between visualizations // to avoid confusing the user. - return suggestion.changeType !== 'extended'; + return ( + suggestion.changeType !== 'extended' && + newVisualization.getVisualizationTypeId(suggestion.visualizationState) === subVisualizationId + ); }); // We prefer unchanged or reduced suggestions when switching diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx index 57588e31590b4..49f2224bf4231 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx @@ -5,7 +5,7 @@ */ import React, { useState } from 'react'; -import { EuiPopover, EuiButtonIcon } from '@elastic/eui'; +import { EuiPopover, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { NativeRenderer } from '../../../native_renderer'; import { Visualization, VisualizationLayerWidgetProps } from '../../../types'; @@ -28,21 +28,27 @@ export function LayerSettings({ return ( setIsOpen(!isOpen)} - data-test-subj="lns_layer_settings" - /> + > + setIsOpen(!isOpen)} + data-test-subj="lns_layer_settings" + /> + } isOpen={isOpen} closePopover={() => setIsOpen(false)} - anchorPosition="leftUp" + anchorPosition="downLeft" > { it('should use suggestions to switch to new visualization', async () => { const initialState = { suggested: true }; mockVisualization2.initialize.mockReturnValueOnce({ initial: true }); + mockVisualization2.getVisualizationTypeId.mockReturnValueOnce('testVis2'); mockVisualization2.getSuggestions.mockReturnValueOnce([ { title: 'Suggested vis', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index 06635e663361d..d8449143b569f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -272,10 +272,10 @@ describe('IndexPattern Data Source', () => { "1", ], "metricsAtAllLevels": Array [ - false, + true, ], "partialRows": Array [ - false, + true, ], "timeFields": Array [ "timestamp", @@ -287,7 +287,7 @@ describe('IndexPattern Data Source', () => { Object { "arguments": Object { "idMap": Array [ - "{\\"col-0-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"sourceField\\":\\"Records\\",\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-1-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}", + "{\\"col--1-col1\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"isBucketed\\":false,\\"sourceField\\":\\"Records\\",\\"operationType\\":\\"count\\",\\"id\\":\\"col1\\"},\\"col-2-col2\\":{\\"label\\":\\"Date\\",\\"dataType\\":\\"date\\",\\"isBucketed\\":true,\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"timestamp\\",\\"params\\":{\\"interval\\":\\"1d\\"},\\"id\\":\\"col2\\"}}", ], }, "function": "lens_rename_columns", diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 1308fa3b7ca60..1dde03ca8ee9b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -26,17 +26,35 @@ function getExpressionForLayer( } const columnEntries = columnOrder.map(colId => [colId, columns[colId]] as const); + const bucketsCount = columnEntries.filter(([, entry]) => entry.isBucketed).length; + const metricsCount = columnEntries.length - bucketsCount; if (columnEntries.length) { const aggs = columnEntries.map(([colId, col]) => { return getEsAggsConfig(col, colId); }); - const idMap = columnEntries.reduce((currentIdMap, [colId], index) => { + /** + * Because we are turning on metrics at all levels, the sequence generation + * logic here is more complicated. Examples follow: + * + * Example 1: [Count] + * Output: [`col-0-count`] + * + * Example 2: [Terms, Terms, Count] + * Output: [`col-0-terms0`, `col-2-terms1`, `col-3-count`] + * + * Example 3: [Terms, Terms, Count, Max] + * Output: [`col-0-terms0`, `col-3-terms1`, `col-4-count`, `col-5-max`] + */ + const idMap = columnEntries.reduce((currentIdMap, [colId, column], index) => { + const newIndex = column.isBucketed + ? index * (metricsCount + 1) // Buckets are spaced apart by N + 1 + : (index ? index + 1 : 0) - bucketsCount + (bucketsCount - 1) * (metricsCount + 1); return { ...currentIdMap, - [`col-${index}-${colId}`]: { - ...columns[colId], + [`col-${columnEntries.length === 1 ? 0 : newIndex}-${colId}`]: { + ...column, id: colId, }, }; @@ -83,8 +101,8 @@ function getExpressionForLayer( function: 'esaggs', arguments: { index: [indexPattern.id], - metricsAtAllLevels: [false], - partialRows: [false], + metricsAtAllLevels: [true], + partialRows: [true], includeFormatHints: [true], timeFields: allDateHistogramFields, aggConfigs: [JSON.stringify(aggs)], diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts index ef93f0b5bf064..173119714189d 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.test.ts @@ -101,7 +101,7 @@ describe('metric_suggestions', () => { expect(suggestion).toMatchInlineSnapshot(` Object { "previewIcon": "test-file-stub", - "score": 0.5, + "score": 0.1, "state": Object { "accessor": "bytes", "layerId": "l1", diff --git a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts index 23df3f55f2777..0caac7dd0d092 100644 --- a/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts +++ b/x-pack/plugins/lens/public/metric_visualization/metric_suggestions.ts @@ -43,7 +43,7 @@ function getSuggestion(table: TableSuggestion): VisualizationSuggestion { return { title, - score: 0.5, + score: 0.1, previewIcon: chartMetricSVG, state: { layerId: table.layerId, diff --git a/x-pack/plugins/lens/public/pie_visualization/constants.ts b/x-pack/plugins/lens/public/pie_visualization/constants.ts new file mode 100644 index 0000000000000..10672f91a81c7 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/constants.ts @@ -0,0 +1,36 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import chartDonutSVG from '../assets/chart_donut.svg'; +import chartPieSVG from '../assets/chart_pie.svg'; +import chartTreemapSVG from '../assets/chart_treemap.svg'; + +export const CHART_NAMES = { + donut: { + icon: chartDonutSVG, + label: i18n.translate('xpack.lens.pie.donutLabel', { + defaultMessage: 'Donut', + }), + }, + pie: { + icon: chartPieSVG, + label: i18n.translate('xpack.lens.pie.pielabel', { + defaultMessage: 'Pie', + }), + }, + treemap: { + icon: chartTreemapSVG, + label: i18n.translate('xpack.lens.pie.treemaplabel', { + defaultMessage: 'Treemap', + }), + }, +}; + +export const MAX_PIE_BUCKETS = 3; +export const MAX_TREEMAP_BUCKETS = 2; + +export const DEFAULT_PERCENT_DECIMALS = 3; diff --git a/x-pack/plugins/lens/public/pie_visualization/index.ts b/x-pack/plugins/lens/public/pie_visualization/index.ts new file mode 100644 index 0000000000000..b2aae2e8529a5 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/index.ts @@ -0,0 +1,53 @@ +/* + * 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 { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; +import { CoreSetup, CoreStart } from 'src/core/public'; +import { ExpressionsSetup } from 'src/plugins/expressions/public'; +import { pieVisualization } from './pie_visualization'; +import { pie, getPieRenderer } from './register_expression'; +import { EditorFrameSetup, FormatFactory } from '../types'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { setExecuteTriggerActions } from '../services'; + +export interface PieVisualizationPluginSetupPlugins { + editorFrame: EditorFrameSetup; + expressions: ExpressionsSetup; + formatFactory: Promise; +} + +export interface PieVisualizationPluginStartPlugins { + uiActions: UiActionsStart; +} + +export class PieVisualization { + constructor() {} + + setup( + core: CoreSetup, + { expressions, formatFactory, editorFrame }: PieVisualizationPluginSetupPlugins + ) { + expressions.registerFunction(() => pie); + + expressions.registerRenderer( + getPieRenderer({ + formatFactory, + chartTheme: core.uiSettings.get('theme:darkMode') + ? EUI_CHARTS_THEME_DARK.theme + : EUI_CHARTS_THEME_LIGHT.theme, + isDarkMode: core.uiSettings.get('theme:darkMode'), + }) + ); + + editorFrame.registerVisualization(pieVisualization); + } + + start(core: CoreStart, { uiActions }: PieVisualizationPluginStartPlugins) { + setExecuteTriggerActions(uiActions.executeTriggerActions); + } + + stop() {} +} diff --git a/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx new file mode 100644 index 0000000000000..78e13bc51588c --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/pie_visualization.tsx @@ -0,0 +1,215 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { render } from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { I18nProvider } from '@kbn/i18n/react'; +import { Visualization, OperationMetadata } from '../types'; +import { toExpression, toPreviewExpression } from './to_expression'; +import { LayerState, PieVisualizationState } from './types'; +import { suggestions } from './suggestions'; +import { CHART_NAMES, MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS } from './constants'; +import { SettingsWidget } from './settings_widget'; + +function newLayerState(layerId: string): LayerState { + return { + layerId, + groups: [], + metric: undefined, + numberDisplay: 'percent', + categoryDisplay: 'default', + legendDisplay: 'default', + nestedLegend: false, + }; +} + +const bucketedOperations = (op: OperationMetadata) => op.isBucketed; +const numberMetricOperations = (op: OperationMetadata) => + !op.isBucketed && op.dataType === 'number'; + +export const pieVisualization: Visualization = { + id: 'lnsPie', + + visualizationTypes: [ + { + id: 'donut', + largeIcon: CHART_NAMES.donut.icon, + label: CHART_NAMES.donut.label, + }, + { + id: 'pie', + largeIcon: CHART_NAMES.pie.icon, + label: CHART_NAMES.pie.label, + }, + { + id: 'treemap', + largeIcon: CHART_NAMES.treemap.icon, + label: CHART_NAMES.treemap.label, + }, + ], + + getVisualizationTypeId(state) { + return state.shape; + }, + + getLayerIds(state) { + return state.layers.map(l => l.layerId); + }, + + clearLayer(state) { + return { + shape: state.shape, + layers: state.layers.map(l => newLayerState(l.layerId)), + }; + }, + + getDescription(state) { + if (state.shape === 'treemap') { + return CHART_NAMES.treemap; + } + if (state.shape === 'donut') { + return CHART_NAMES.donut; + } + return CHART_NAMES.pie; + }, + + switchVisualizationType: (visualizationTypeId, state) => ({ + ...state, + shape: visualizationTypeId as PieVisualizationState['shape'], + }), + + initialize(frame, state) { + return ( + state || { + shape: 'donut', + layers: [newLayerState(frame.addNewLayer())], + } + ); + }, + + getPersistableState: state => state, + + getSuggestions: suggestions, + + getConfiguration({ state, frame, layerId }) { + const layer = state.layers.find(l => l.layerId === layerId); + if (!layer) { + return { groups: [] }; + } + + const datasource = frame.datasourceLayers[layer.layerId]; + const originalOrder = datasource + .getTableSpec() + .map(({ columnId }) => columnId) + .filter(columnId => columnId !== layer.metric); + // When we add a column it could be empty, and therefore have no order + const sortedColumns = Array.from(new Set(originalOrder.concat(layer.groups))); + + if (state.shape === 'treemap') { + return { + groups: [ + { + groupId: 'groups', + groupLabel: i18n.translate('xpack.lens.pie.treemapGroupLabel', { + defaultMessage: 'Group by', + }), + layerId, + accessors: sortedColumns, + supportsMoreColumns: sortedColumns.length < MAX_TREEMAP_BUCKETS, + filterOperations: bucketedOperations, + required: true, + }, + { + groupId: 'metric', + groupLabel: i18n.translate('xpack.lens.pie.groupsizeLabel', { + defaultMessage: 'Size by', + }), + layerId, + accessors: layer.metric ? [layer.metric] : [], + supportsMoreColumns: !layer.metric, + filterOperations: numberMetricOperations, + required: true, + }, + ], + }; + } + + return { + groups: [ + { + groupId: 'groups', + groupLabel: i18n.translate('xpack.lens.pie.sliceGroupLabel', { + defaultMessage: 'Slice by', + }), + layerId, + accessors: sortedColumns, + supportsMoreColumns: sortedColumns.length < MAX_PIE_BUCKETS, + filterOperations: bucketedOperations, + required: true, + }, + { + groupId: 'metric', + groupLabel: i18n.translate('xpack.lens.pie.groupsizeLabel', { + defaultMessage: 'Size by', + }), + layerId, + accessors: layer.metric ? [layer.metric] : [], + supportsMoreColumns: !layer.metric, + filterOperations: numberMetricOperations, + required: true, + }, + ], + }; + }, + + setDimension({ prevState, layerId, columnId, groupId }) { + return { + ...prevState, + + shape: + prevState.shape === 'donut' && prevState.layers.every(l => l.groups.length === 1) + ? 'pie' + : prevState.shape, + layers: prevState.layers.map(l => { + if (l.layerId !== layerId) { + return l; + } + if (groupId === 'groups') { + return { ...l, groups: [...l.groups, columnId] }; + } + return { ...l, metric: columnId }; + }), + }; + }, + removeDimension({ prevState, layerId, columnId }) { + return { + ...prevState, + layers: prevState.layers.map(l => { + if (l.layerId !== layerId) { + return l; + } + + if (l.metric === columnId) { + return { ...l, metric: undefined }; + } + return { ...l, groups: l.groups.filter(c => c !== columnId) }; + }), + }; + }, + + toExpression, + toPreviewExpression, + + renderLayerContextMenu(domElement, props) { + render( + + + , + domElement + ); + }, +}; diff --git a/x-pack/plugins/lens/public/pie_visualization/register_expression.tsx b/x-pack/plugins/lens/public/pie_visualization/register_expression.tsx new file mode 100644 index 0000000000000..998d2162f7f5d --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/register_expression.tsx @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { i18n } from '@kbn/i18n'; +import { PartialTheme } from '@elastic/charts'; +import { + IInterpreterRenderHandlers, + ExpressionRenderDefinition, + ExpressionFunctionDefinition, +} from 'src/plugins/expressions/public'; +import { LensMultiTable, FormatFactory } from '../types'; +import { PieExpressionProps, PieExpressionArgs } from './types'; +import { getExecuteTriggerActions } from '../services'; +import { PieComponent } from './render_function'; + +export interface PieRender { + type: 'render'; + as: 'lens_pie_renderer'; + value: PieExpressionProps; +} + +export const pie: ExpressionFunctionDefinition< + 'lens_pie', + LensMultiTable, + PieExpressionArgs, + PieRender +> = { + name: 'lens_pie', + type: 'render', + help: i18n.translate('xpack.lens.pie.expressionHelpLabel', { + defaultMessage: 'Pie renderer', + }), + args: { + groups: { + types: ['string'], + multi: true, + help: '', + }, + metric: { + types: ['string'], + help: '', + }, + shape: { + types: ['string'], + options: ['pie', 'donut', 'treemap'], + help: '', + }, + hideLabels: { + types: ['boolean'], + help: '', + }, + numberDisplay: { + types: ['string'], + options: ['hidden', 'percent', 'value'], + help: '', + }, + categoryDisplay: { + types: ['string'], + options: ['default', 'inside', 'hide'], + help: '', + }, + legendDisplay: { + types: ['string'], + options: ['default', 'show', 'hide'], + help: '', + }, + nestedLegend: { + types: ['boolean'], + help: '', + }, + percentDecimals: { + types: ['number'], + help: '', + }, + }, + inputTypes: ['lens_multitable'], + fn(data: LensMultiTable, args: PieExpressionArgs) { + return { + type: 'render', + as: 'lens_pie_renderer', + value: { + data, + args, + }, + }; + }, +}; + +export const getPieRenderer = (dependencies: { + formatFactory: Promise; + chartTheme: PartialTheme; + isDarkMode: boolean; +}): ExpressionRenderDefinition => ({ + name: 'lens_pie_renderer', + displayName: i18n.translate('xpack.lens.pie.visualizationName', { + defaultMessage: 'Pie', + }), + help: '', + validate: () => undefined, + reuseDomNode: true, + render: async ( + domNode: Element, + config: PieExpressionProps, + handlers: IInterpreterRenderHandlers + ) => { + const executeTriggerActions = getExecuteTriggerActions(); + const formatFactory = await dependencies.formatFactory; + ReactDOM.render( + , + domNode, + () => { + handlers.done(); + } + ); + handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode)); + }, +}); + +const MemoizedChart = React.memo(PieComponent); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx new file mode 100644 index 0000000000000..bdc8004540bae --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.test.tsx @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { Settings } from '@elastic/charts'; +import { shallow } from 'enzyme'; +import { LensMultiTable } from '../types'; +import { PieComponent } from './render_function'; +import { PieExpressionArgs } from './types'; + +describe('PieVisualization component', () => { + let getFormatSpy: jest.Mock; + let convertSpy: jest.Mock; + + beforeEach(() => { + convertSpy = jest.fn(x => x); + getFormatSpy = jest.fn(); + getFormatSpy.mockReturnValue({ convert: convertSpy }); + }); + + describe('legend options', () => { + const data: LensMultiTable = { + type: 'lens_multitable', + tables: { + first: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + ], + rows: [ + { a: 6, b: 2, c: 'I', d: 'Row 1' }, + { a: 1, b: 5, c: 'J', d: 'Row 2' }, + ], + }, + }, + }; + + const args: PieExpressionArgs = { + shape: 'pie', + groups: ['a', 'b'], + metric: 'c', + numberDisplay: 'hidden', + categoryDisplay: 'default', + legendDisplay: 'default', + nestedLegend: false, + percentDecimals: 3, + hideLabels: false, + }; + + function getDefaultArgs() { + return { + data, + formatFactory: getFormatSpy, + isDarkMode: false, + chartTheme: {}, + executeTriggerActions: jest.fn(), + }; + } + + test('it shows legend for 2 groups using default legendDisplay', () => { + const component = shallow(); + expect(component.find(Settings).prop('showLegend')).toEqual(true); + }); + + test('it hides legend for 1 group using default legendDisplay', () => { + const component = shallow( + + ); + expect(component.find(Settings).prop('showLegend')).toEqual(false); + }); + + test('it hides legend that would show otherwise in preview mode', () => { + const component = shallow( + + ); + expect(component.find(Settings).prop('showLegend')).toEqual(false); + }); + + test('it hides legend with 2 groups for treemap', () => { + const component = shallow( + + ); + expect(component.find(Settings).prop('showLegend')).toEqual(false); + }); + + test('it shows treemap legend only when forced on', () => { + const component = shallow( + + ); + expect(component.find(Settings).prop('showLegend')).toEqual(true); + }); + + test('it defaults to 1-level legend depth', () => { + const component = shallow(); + expect(component.find(Settings).prop('legendMaxDepth')).toEqual(1); + }); + + test('it shows nested legend only when forced on', () => { + const component = shallow( + + ); + expect(component.find(Settings).prop('legendMaxDepth')).toBeUndefined(); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_function.tsx b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx new file mode 100644 index 0000000000000..f451a6b74e299 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/render_function.tsx @@ -0,0 +1,259 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useEffect } from 'react'; +import color from 'color'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiText } from '@elastic/eui'; +// @ts-ignore no types +import { euiPaletteColorBlindBehindText } from '@elastic/eui/lib/services'; +import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json'; +import { + Chart, + Datum, + Settings, + Partition, + PartitionConfig, + PartitionLayer, + PartitionLayout, + PartialTheme, + PartitionFillLabel, + RecursivePartial, + LayerValue, +} from '@elastic/charts'; +import { VIS_EVENT_TO_TRIGGER } from '../../../../../src/plugins/visualizations/public'; +import { FormatFactory } from '../types'; +import { VisualizationContainer } from '../visualization_container'; +import { CHART_NAMES, DEFAULT_PERCENT_DECIMALS } from './constants'; +import { ColumnGroups, PieExpressionProps } from './types'; +import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; +import { getSliceValueWithFallback, getFilterContext } from './render_helpers'; +import './visualization.scss'; + +const EMPTY_SLICE = Symbol('empty_slice'); + +const sortedColors = euiPaletteColorBlindBehindText(); + +export function PieComponent( + props: PieExpressionProps & { + formatFactory: FormatFactory; + chartTheme: Exclude; + isDarkMode: boolean; + executeTriggerActions: UiActionsStart['executeTriggerActions']; + } +) { + const [firstTable] = Object.values(props.data.tables); + const formatters: Record> = {}; + + const { chartTheme, isDarkMode, executeTriggerActions } = props; + const { + shape, + groups, + metric, + numberDisplay, + categoryDisplay, + legendDisplay, + nestedLegend, + percentDecimals, + hideLabels, + } = props.args; + + if (!hideLabels) { + firstTable.columns.forEach(column => { + formatters[column.id] = props.formatFactory(column.formatHint); + }); + } + + // The datatable for pie charts should include subtotals, like this: + // [bucket, subtotal, bucket, count] + // But the user only configured [bucket, bucket, count] + const columnGroups: ColumnGroups = []; + firstTable.columns.forEach(col => { + if (groups.includes(col.id)) { + columnGroups.push({ + col, + metrics: [], + }); + } else if (columnGroups.length > 0) { + columnGroups[columnGroups.length - 1].metrics.push(col); + } + }); + + const fillLabel: Partial = { + textInvertible: false, + valueFont: { + fontWeight: 700, + }, + }; + + if (numberDisplay === 'hidden') { + // Hides numbers from appearing inside chart, but they still appear in linkLabel + // and tooltips. + fillLabel.valueFormatter = () => ''; + } + + const layers: PartitionLayer[] = columnGroups.map(({ col }, layerIndex) => { + return { + groupByRollup: (d: Datum) => d[col.id] ?? EMPTY_SLICE, + showAccessor: (d: Datum) => d !== EMPTY_SLICE, + nodeLabel: (d: unknown) => { + if (hideLabels || d === EMPTY_SLICE) { + return ''; + } + if (col.formatHint) { + return formatters[col.id].convert(d) ?? ''; + } + return String(d); + }, + fillLabel: + isDarkMode && shape === 'treemap' && layerIndex < columnGroups.length - 1 + ? { ...fillLabel, textColor: euiDarkVars.euiTextColor } + : fillLabel, + shape: { + fillColor: d => { + // Color is determined by round-robin on the index of the innermost slice + // This has to be done recursively until we get to the slice index + let parentIndex = 0; + let tempParent: typeof d | typeof d['parent'] = d; + while (tempParent.parent && tempParent.depth > 0) { + parentIndex = tempParent.sortIndex; + tempParent = tempParent.parent; + } + + // Look up round-robin color from default palette + const outputColor = sortedColors[parentIndex % sortedColors.length]; + + if (shape === 'treemap') { + // Only highlight the innermost color of the treemap, as it accurately represents area + return layerIndex < columnGroups.length - 1 ? 'rgba(0,0,0,0)' : outputColor; + } + + const lighten = (d.depth - 1) / (columnGroups.length * 2); + return color(outputColor, 'hsl') + .lighten(lighten) + .hex(); + }, + }, + }; + }); + + const config: RecursivePartial = { + partitionLayout: shape === 'treemap' ? PartitionLayout.treemap : PartitionLayout.sunburst, + fontFamily: chartTheme.barSeriesStyle?.displayValue?.fontFamily, + outerSizeRatio: 1, + specialFirstInnermostSector: true, + clockwiseSectors: false, + minFontSize: 10, + maxFontSize: 16, + // Labels are added outside the outer ring when the slice is too small + linkLabel: { + maxCount: 5, + fontSize: 11, + // Dashboard background color is affected by dark mode, which we need + // to account for in outer labels + // This does not handle non-dashboard embeddables, which are allowed to + // have different backgrounds. + textColor: chartTheme.axes?.axisTitleStyle?.fill, + }, + sectorLineStroke: chartTheme.lineSeriesStyle?.point?.fill, + sectorLineWidth: 1.5, + circlePadding: 4, + }; + if (shape === 'treemap') { + if (hideLabels || categoryDisplay === 'hide') { + config.fillLabel = { textColor: 'rgba(0,0,0,0)' }; + } + } else { + config.emptySizeRatio = shape === 'donut' ? 0.3 : 0; + + if (hideLabels || categoryDisplay === 'hide') { + // Force all labels to be linked, then prevent links from showing + config.linkLabel = { maxCount: 0, maximumSection: Number.POSITIVE_INFINITY }; + } else if (categoryDisplay === 'inside') { + // Prevent links from showing + config.linkLabel = { maxCount: 0 }; + } + } + const metricColumn = firstTable.columns.find(c => c.id === metric)!; + const percentFormatter = props.formatFactory({ + id: 'percent', + params: { + pattern: `0,0.${'0'.repeat(percentDecimals ?? DEFAULT_PERCENT_DECIMALS)}%`, + }, + }); + + const [state, setState] = useState({ isReady: false }); + // It takes a cycle for the chart to render. This prevents + // reporting from printing a blank chart placeholder. + useEffect(() => { + setState({ isReady: true }); + }, []); + + const reverseGroups = [...columnGroups].reverse(); + + const hasNegative = firstTable.rows.some(row => { + const value = row[metricColumn.id]; + return typeof value === 'number' && value < 0; + }); + if (firstTable.rows.length === 0 || hasNegative) { + return ( + + {hasNegative ? ( + + ) : ( + + )} + + ); + } + + return ( + + + + + ); +} diff --git a/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts b/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts new file mode 100644 index 0000000000000..824eec63ba118 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/render_helpers.test.ts @@ -0,0 +1,183 @@ +/* + * 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 { KibanaDatatable } from 'src/plugins/expressions/public'; +import { getSliceValueWithFallback, getFilterContext } from './render_helpers'; + +describe('render helpers', () => { + describe('#getSliceValueWithFallback', () => { + describe('without fallback', () => { + const columnGroups = [ + { col: { id: 'a', name: 'A' }, metrics: [] }, + { col: { id: 'b', name: 'C' }, metrics: [] }, + ]; + + it('returns the metric when positive number', () => { + expect( + getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: 5 }, columnGroups, { + id: 'c', + name: 'C', + }) + ).toEqual(5); + }); + + it('returns the metric when negative number', () => { + expect( + getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: -100 }, columnGroups, { + id: 'c', + name: 'C', + }) + ).toEqual(-100); + }); + + it('returns epsilon when metric is 0 without fallback', () => { + expect( + getSliceValueWithFallback({ a: 'Cat', b: 'Home', c: 0 }, columnGroups, { + id: 'c', + name: 'C', + }) + ).toEqual(Number.EPSILON); + }); + }); + + describe('fallback behavior', () => { + const columnGroups = [ + { col: { id: 'a', name: 'A' }, metrics: [{ id: 'a_subtotal', name: '' }] }, + { col: { id: 'b', name: 'C' }, metrics: [] }, + ]; + + it('falls back to metric from previous column if available', () => { + expect( + getSliceValueWithFallback( + { a: 'Cat', a_subtotal: 5, b: 'Home', c: undefined }, + columnGroups, + { id: 'c', name: 'C' } + ) + ).toEqual(5); + }); + + it('uses epsilon if fallback is 0', () => { + expect( + getSliceValueWithFallback( + { a: 'Cat', a_subtotal: 0, b: 'Home', c: undefined }, + columnGroups, + { id: 'c', name: 'C' } + ) + ).toEqual(Number.EPSILON); + }); + + it('uses epsilon if fallback is missing', () => { + expect( + getSliceValueWithFallback( + { a: 'Cat', a_subtotal: undefined, b: 'Home', c: undefined }, + columnGroups, + { id: 'c', name: 'C' } + ) + ).toEqual(Number.EPSILON); + }); + }); + }); + + describe('#getFilterContext', () => { + it('handles single slice click for single ring', () => { + const table: KibanaDatatable = { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'A' }, + { id: 'b', name: 'B' }, + ], + rows: [ + { a: 'Hi', b: 2 }, + { a: 'Test', b: 4 }, + { a: 'Foo', b: 6 }, + ], + }; + expect(getFilterContext([{ groupByRollup: 'Test', value: 100 }], ['a'], table)).toEqual({ + data: { + data: [ + { + row: 1, + column: 0, + value: 'Test', + table, + }, + ], + }, + }); + }); + + it('handles single slice click with 2 rings', () => { + const table: KibanaDatatable = { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'A' }, + { id: 'b', name: 'B' }, + { id: 'c', name: 'C' }, + ], + rows: [ + { a: 'Hi', b: 'Two', c: 2 }, + { a: 'Test', b: 'Two', c: 5 }, + { a: 'Foo', b: 'Three', c: 6 }, + ], + }; + expect(getFilterContext([{ groupByRollup: 'Test', value: 100 }], ['a', 'b'], table)).toEqual({ + data: { + data: [ + { + row: 1, + column: 0, + value: 'Test', + table, + }, + ], + }, + }); + }); + + it('finds right row for multi slice click', () => { + const table: KibanaDatatable = { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'A' }, + { id: 'b', name: 'B' }, + { id: 'c', name: 'C' }, + ], + rows: [ + { a: 'Hi', b: 'Two', c: 2 }, + { a: 'Test', b: 'Two', c: 5 }, + { a: 'Foo', b: 'Three', c: 6 }, + ], + }; + expect( + getFilterContext( + [ + { groupByRollup: 'Test', value: 100 }, + { groupByRollup: 'Two', value: 5 }, + ], + ['a', 'b'], + table + ) + ).toEqual({ + data: { + data: [ + { + row: 1, + column: 0, + value: 'Test', + table, + }, + { + row: 1, + column: 1, + value: 'Two', + table, + }, + ], + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts b/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts new file mode 100644 index 0000000000000..bc3c29ba0fff1 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/render_helpers.ts @@ -0,0 +1,49 @@ +/* + * 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 { Datum, LayerValue } from '@elastic/charts'; +import { KibanaDatatable, KibanaDatatableColumn } from 'src/plugins/expressions/public'; +import { ValueClickTriggerContext } from '../../../../../src/plugins/embeddable/public'; +import { ColumnGroups } from './types'; + +export function getSliceValueWithFallback( + d: Datum, + reverseGroups: ColumnGroups, + metricColumn: KibanaDatatableColumn +) { + if (typeof d[metricColumn.id] === 'number' && d[metricColumn.id] !== 0) { + return d[metricColumn.id]; + } + // Sometimes there is missing data for outer groups + // When there is missing data, we fall back to the next groups + // This creates a sunburst effect + const hasMetric = reverseGroups.find(group => group.metrics.length && d[group.metrics[0].id]); + return hasMetric ? d[hasMetric.metrics[0].id] || Number.EPSILON : Number.EPSILON; +} + +export function getFilterContext( + clickedLayers: LayerValue[], + layerColumnIds: string[], + table: KibanaDatatable +): ValueClickTriggerContext { + const matchingIndex = table.rows.findIndex(row => + clickedLayers.every((layer, index) => { + const columnId = layerColumnIds[index]; + return row[columnId] === layer.groupByRollup; + }) + ); + + return { + data: { + data: clickedLayers.map((clickedLayer, index) => ({ + column: table.columns.findIndex(col => col.id === layerColumnIds[index]), + row: matchingIndex, + value: clickedLayer.groupByRollup, + table, + })), + }, + }; +} diff --git a/x-pack/plugins/lens/public/pie_visualization/settings_widget.scss b/x-pack/plugins/lens/public/pie_visualization/settings_widget.scss new file mode 100644 index 0000000000000..4fa328d8a904d --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/settings_widget.scss @@ -0,0 +1,3 @@ +.lnsPieSettingsWidget { + min-width: $euiSizeXL * 10; +} diff --git a/x-pack/plugins/lens/public/pie_visualization/settings_widget.tsx b/x-pack/plugins/lens/public/pie_visualization/settings_widget.tsx new file mode 100644 index 0000000000000..5a02b91efc749 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/settings_widget.tsx @@ -0,0 +1,212 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiForm, + EuiFormRow, + EuiSuperSelect, + EuiRange, + EuiSwitch, + EuiHorizontalRule, + EuiSpacer, + EuiButtonGroup, +} from '@elastic/eui'; +import { DEFAULT_PERCENT_DECIMALS } from './constants'; +import { PieVisualizationState, SharedLayerState } from './types'; +import { VisualizationLayerWidgetProps } from '../types'; +import './settings_widget.scss'; + +const numberOptions: Array<{ value: SharedLayerState['numberDisplay']; inputDisplay: string }> = [ + { + value: 'hidden', + inputDisplay: i18n.translate('xpack.lens.pieChart.hiddenNumbersLabel', { + defaultMessage: 'Hide from chart', + }), + }, + { + value: 'percent', + inputDisplay: i18n.translate('xpack.lens.pieChart.showPercentValuesLabel', { + defaultMessage: 'Show percent', + }), + }, + { + value: 'value', + inputDisplay: i18n.translate('xpack.lens.pieChart.showFormatterValuesLabel', { + defaultMessage: 'Show value', + }), + }, +]; + +const categoryOptions: Array<{ + value: SharedLayerState['categoryDisplay']; + inputDisplay: string; +}> = [ + { + value: 'default', + inputDisplay: i18n.translate('xpack.lens.pieChart.showCategoriesLabel', { + defaultMessage: 'Inside or outside', + }), + }, + { + value: 'inside', + inputDisplay: i18n.translate('xpack.lens.pieChart.fitInsideOnlyLabel', { + defaultMessage: 'Inside only', + }), + }, + { + value: 'hide', + inputDisplay: i18n.translate('xpack.lens.pieChart.categoriesInLegendLabel', { + defaultMessage: 'Hide labels', + }), + }, +]; + +const legendOptions: Array<{ + value: SharedLayerState['legendDisplay']; + label: string; + id: string; +}> = [ + { + id: 'pieLegendDisplay-default', + value: 'default', + label: i18n.translate('xpack.lens.pieChart.defaultLegendLabel', { + defaultMessage: 'auto', + }), + }, + { + id: 'pieLegendDisplay-show', + value: 'show', + label: i18n.translate('xpack.lens.pieChart.alwaysShowLegendLabel', { + defaultMessage: 'show', + }), + }, + { + id: 'pieLegendDisplay-hide', + value: 'hide', + label: i18n.translate('xpack.lens.pieChart.hideLegendLabel', { + defaultMessage: 'hide', + }), + }, +]; + +export function SettingsWidget(props: VisualizationLayerWidgetProps) { + const { state, setState } = props; + const layer = state.layers[0]; + if (!layer) { + return null; + } + + return ( + + + { + setState({ + ...state, + layers: [{ ...layer, categoryDisplay: option }], + }); + }} + /> + + + { + setState({ + ...state, + layers: [{ ...layer, numberDisplay: option }], + }); + }} + /> + + + + { + setState({ + ...state, + layers: [{ ...layer, percentDecimals: Number(e.currentTarget.value) }], + }); + }} + /> + + + +
+ value === layer.legendDisplay)!.id} + onChange={optionId => { + setState({ + ...state, + layers: [ + { + ...layer, + legendDisplay: legendOptions.find(({ id }) => id === optionId)!.value, + }, + ], + }); + }} + buttonSize="compressed" + isFullWidth + /> + + + { + setState({ ...state, layers: [{ ...layer, nestedLegend: !layer.nestedLegend }] }); + }} + /> +
+
+
+ ); +} diff --git a/x-pack/plugins/lens/public/pie_visualization/suggestions.test.ts b/x-pack/plugins/lens/public/pie_visualization/suggestions.test.ts new file mode 100644 index 0000000000000..7935d53f56845 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/suggestions.test.ts @@ -0,0 +1,522 @@ +/* + * 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 { DataType } from '../types'; +import { suggestions } from './suggestions'; + +describe('suggestions', () => { + describe('pie', () => { + it('should reject multiple layer suggestions', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first', 'second'], + }) + ).toHaveLength(0); + }); + + it('should reject when layer is different', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['second'], + }) + ).toHaveLength(0); + }); + + it('should reject when currently active and unchanged data', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [], + changeType: 'unchanged', + }, + state: { + shape: 'pie', + layers: [ + { + layerId: 'first', + groups: [], + metric: 'a', + numberDisplay: 'hidden', + categoryDisplay: 'default', + legendDisplay: 'default', + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when table is reordered', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [], + changeType: 'reorder', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject any date operations', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'b', + operation: { label: 'Days', dataType: 'date' as DataType, isBucketed: true }, + }, + { + columnId: 'c', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are no buckets', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'c', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are no metrics', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'c', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: true }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are too many buckets', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'c', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'd', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are too many metrics', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'c', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'd', + operation: { label: 'Avg', dataType: 'number' as DataType, isBucketed: false }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should suggest a donut chart as initial state when only one bucket', () => { + const results = suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }); + + expect(results).toContainEqual( + expect.objectContaining({ + state: expect.objectContaining({ shape: 'donut' }), + }) + ); + }); + + it('should suggest a pie chart as initial state when more than one bucket', () => { + const results = suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: undefined, + keptLayerIds: ['first'], + }); + + expect(results).toContainEqual( + expect.objectContaining({ + state: expect.objectContaining({ shape: 'pie' }), + }) + ); + }); + + it('should keep the layer settings when switching from treemap', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'unchanged', + }, + state: { + shape: 'treemap', + layers: [ + { + layerId: 'first', + groups: ['a'], + metric: 'b', + + numberDisplay: 'hidden', + categoryDisplay: 'inside', + legendDisplay: 'show', + percentDecimals: 0, + nestedLegend: true, + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toContainEqual( + expect.objectContaining({ + state: { + shape: 'donut', + layers: [ + { + layerId: 'first', + groups: ['a'], + metric: 'b', + + numberDisplay: 'hidden', + categoryDisplay: 'inside', + legendDisplay: 'show', + percentDecimals: 0, + nestedLegend: true, + }, + ], + }, + }) + ); + }); + }); + + describe('treemap', () => { + it('should reject when currently active and unchanged data', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [], + changeType: 'unchanged', + }, + state: { + shape: 'treemap', + layers: [ + { + layerId: 'first', + groups: [], + metric: 'a', + + numberDisplay: 'hidden', + categoryDisplay: 'default', + legendDisplay: 'default', + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are too many buckets being added', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'c', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'd', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'extended', + }, + state: { + shape: 'treemap', + layers: [ + { + layerId: 'first', + groups: ['a', 'b'], + metric: 'e', + numberDisplay: 'value', + categoryDisplay: 'default', + legendDisplay: 'default', + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should reject when there are too many metrics', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'c', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'd', + operation: { label: 'Avg', dataType: 'number' as DataType, isBucketed: false }, + }, + { + columnId: 'e', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'initial', + }, + state: { + shape: 'treemap', + layers: [ + { + layerId: 'first', + groups: ['a', 'b'], + metric: 'e', + numberDisplay: 'percent', + categoryDisplay: 'default', + legendDisplay: 'default', + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toHaveLength(0); + }); + + it('should keep the layer settings when switching from pie', () => { + expect( + suggestions({ + table: { + layerId: 'first', + isMultiRow: true, + columns: [ + { + columnId: 'a', + operation: { label: 'Top 5', dataType: 'string' as DataType, isBucketed: true }, + }, + { + columnId: 'b', + operation: { label: 'Count', dataType: 'number' as DataType, isBucketed: false }, + }, + ], + changeType: 'unchanged', + }, + state: { + shape: 'pie', + layers: [ + { + layerId: 'first', + groups: ['a'], + metric: 'b', + + numberDisplay: 'hidden', + categoryDisplay: 'inside', + legendDisplay: 'show', + percentDecimals: 0, + nestedLegend: true, + }, + ], + }, + keptLayerIds: ['first'], + }) + ).toContainEqual( + expect.objectContaining({ + state: { + shape: 'treemap', + layers: [ + { + layerId: 'first', + groups: ['a'], + metric: 'b', + + numberDisplay: 'hidden', + categoryDisplay: 'inside', + legendDisplay: 'show', + percentDecimals: 0, + nestedLegend: true, + }, + ], + }, + }) + ); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/pie_visualization/suggestions.ts b/x-pack/plugins/lens/public/pie_visualization/suggestions.ts new file mode 100644 index 0000000000000..e363cf922b356 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/suggestions.ts @@ -0,0 +1,137 @@ +/* + * 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 { partition } from 'lodash'; +import { i18n } from '@kbn/i18n'; +import { SuggestionRequest, VisualizationSuggestion } from '../types'; +import { PieVisualizationState } from './types'; +import { CHART_NAMES, MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS } from './constants'; + +function shouldReject({ table, keptLayerIds }: SuggestionRequest) { + return ( + keptLayerIds.length > 1 || + (keptLayerIds.length && table.layerId !== keptLayerIds[0]) || + table.changeType === 'reorder' || + table.columns.some(col => col.operation.dataType === 'date') + ); +} + +export function suggestions({ + table, + state, + keptLayerIds, +}: SuggestionRequest): Array< + VisualizationSuggestion +> { + if (shouldReject({ table, state, keptLayerIds })) { + return []; + } + + const [groups, metrics] = partition(table.columns, col => col.operation.isBucketed); + + if ( + groups.length === 0 || + metrics.length !== 1 || + groups.length > Math.max(MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS) + ) { + return []; + } + + const results: Array> = []; + + if (groups.length <= MAX_PIE_BUCKETS) { + let newShape: PieVisualizationState['shape'] = 'donut'; + if (groups.length !== 1) { + newShape = 'pie'; + } + + const baseSuggestion: VisualizationSuggestion = { + title: i18n.translate('xpack.lens.pie.suggestionLabel', { + defaultMessage: 'As {chartName}', + values: { chartName: CHART_NAMES[newShape].label }, + description: 'chartName is already translated', + }), + score: state && state.shape !== 'treemap' ? 0.6 : 0.4, + state: { + shape: newShape, + layers: [ + state?.layers[0] + ? { + ...state.layers[0], + layerId: table.layerId, + groups: groups.map(col => col.columnId), + metric: metrics[0].columnId, + } + : { + layerId: table.layerId, + groups: groups.map(col => col.columnId), + metric: metrics[0].columnId, + numberDisplay: 'percent', + categoryDisplay: 'default', + legendDisplay: 'default', + nestedLegend: false, + }, + ], + }, + previewIcon: 'bullseye', + // dont show suggestions for same type + hide: table.changeType === 'reduced' || (state && state.shape !== 'treemap'), + }; + + results.push(baseSuggestion); + results.push({ + ...baseSuggestion, + title: i18n.translate('xpack.lens.pie.suggestionLabel', { + defaultMessage: 'As {chartName}', + values: { chartName: CHART_NAMES[newShape === 'pie' ? 'donut' : 'pie'].label }, + description: 'chartName is already translated', + }), + score: 0.1, + state: { + ...baseSuggestion.state, + shape: newShape === 'pie' ? 'donut' : 'pie', + }, + hide: true, + }); + } + + if (groups.length <= MAX_TREEMAP_BUCKETS) { + results.push({ + title: i18n.translate('xpack.lens.pie.treemapSuggestionLabel', { + defaultMessage: 'As Treemap', + }), + // Use a higher score when currently active, to prevent chart type switching + // on the user unintentionally + score: state?.shape === 'treemap' ? 0.7 : 0.5, + state: { + shape: 'treemap', + layers: [ + state?.layers[0] + ? { + ...state.layers[0], + layerId: table.layerId, + groups: groups.map(col => col.columnId), + metric: metrics[0].columnId, + } + : { + layerId: table.layerId, + groups: groups.map(col => col.columnId), + metric: metrics[0].columnId, + numberDisplay: 'percent', + categoryDisplay: 'default', + legendDisplay: 'default', + nestedLegend: false, + }, + ], + }, + previewIcon: 'bullseye', + // hide treemap suggestions from bottom bar, but keep them for chart switcher + hide: table.changeType === 'reduced' || !state || (state && state.shape === 'treemap'), + }); + } + + return [...results].sort((a, b) => a.score - b.score); +} diff --git a/x-pack/plugins/lens/public/pie_visualization/to_expression.ts b/x-pack/plugins/lens/public/pie_visualization/to_expression.ts new file mode 100644 index 0000000000000..4a7272b26a63f --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/to_expression.ts @@ -0,0 +1,54 @@ +/* + * 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 { Ast } from '@kbn/interpreter/common'; +import { FramePublicAPI, Operation } from '../types'; +import { DEFAULT_PERCENT_DECIMALS } from './constants'; +import { PieVisualizationState } from './types'; + +export function toExpression(state: PieVisualizationState, frame: FramePublicAPI) { + return expressionHelper(state, frame, false); +} + +function expressionHelper( + state: PieVisualizationState, + frame: FramePublicAPI, + isPreview: boolean +): Ast | null { + const layer = state.layers[0]; + const datasource = frame.datasourceLayers[layer.layerId]; + const operations = layer.groups + .map(columnId => ({ columnId, operation: datasource.getOperationForColumnId(columnId) })) + .filter((o): o is { columnId: string; operation: Operation } => !!o.operation); + if (!layer.metric || !operations.length) { + return null; + } + + return { + type: 'expression', + chain: [ + { + type: 'function', + function: 'lens_pie', + arguments: { + shape: [state.shape], + hideLabels: [isPreview], + groups: operations.map(o => o.columnId), + metric: [layer.metric], + numberDisplay: [layer.numberDisplay], + categoryDisplay: [layer.categoryDisplay], + legendDisplay: [layer.legendDisplay], + percentDecimals: [layer.percentDecimals ?? DEFAULT_PERCENT_DECIMALS], + nestedLegend: [!!layer.nestedLegend], + }, + }, + ], + }; +} + +export function toPreviewExpression(state: PieVisualizationState, frame: FramePublicAPI) { + return expressionHelper(state, frame, true); +} diff --git a/x-pack/plugins/lens/public/pie_visualization/types.ts b/x-pack/plugins/lens/public/pie_visualization/types.ts new file mode 100644 index 0000000000000..60b6564248640 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/types.ts @@ -0,0 +1,42 @@ +/* + * 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 { KibanaDatatableColumn } from 'src/plugins/expressions/public'; +import { LensMultiTable } from '../types'; + +export interface SharedLayerState { + groups: string[]; + metric?: string; + numberDisplay: 'hidden' | 'percent' | 'value'; + categoryDisplay: 'default' | 'inside' | 'hide'; + legendDisplay: 'default' | 'show' | 'hide'; + nestedLegend?: boolean; + percentDecimals?: number; +} + +export type LayerState = SharedLayerState & { + layerId: string; +}; + +export interface PieVisualizationState { + shape: 'donut' | 'pie' | 'treemap'; + layers: LayerState[]; +} + +export type PieExpressionArgs = SharedLayerState & { + shape: 'pie' | 'donut' | 'treemap'; + hideLabels: boolean; +}; + +export interface PieExpressionProps { + data: LensMultiTable; + args: PieExpressionArgs; +} + +export type ColumnGroups = Array<{ + col: KibanaDatatableColumn; + metrics: KibanaDatatableColumn[]; +}>; diff --git a/x-pack/plugins/lens/public/pie_visualization/visualization.scss b/x-pack/plugins/lens/public/pie_visualization/visualization.scss new file mode 100644 index 0000000000000..d9ff75d849708 --- /dev/null +++ b/x-pack/plugins/lens/public/pie_visualization/visualization.scss @@ -0,0 +1,4 @@ +.lnsPieExpression__container { + height: 100%; + width: 100%; +} diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index a6acc61922177..a8ec525604977 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -16,6 +16,7 @@ import { IndexPatternDatasource } from './indexpattern_datasource'; import { XyVisualization } from './xy_visualization'; import { MetricVisualization } from './metric_visualization'; import { DatatableVisualization } from './datatable_visualization'; +import { PieVisualization } from './pie_visualization'; import { stopReportManager } from './lens_ui_telemetry'; import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; @@ -48,6 +49,7 @@ export class LensPlugin { private indexpatternDatasource: IndexPatternDatasource; private xyVisualization: XyVisualization; private metricVisualization: MetricVisualization; + private pieVisualization: PieVisualization; constructor() { this.datatableVisualization = new DatatableVisualization(); @@ -55,6 +57,7 @@ export class LensPlugin { this.indexpatternDatasource = new IndexPatternDatasource(); this.xyVisualization = new XyVisualization(); this.metricVisualization = new MetricVisualization(); + this.pieVisualization = new PieVisualization(); } setup( @@ -78,6 +81,7 @@ export class LensPlugin { this.xyVisualization.setup(core, dependencies); this.datatableVisualization.setup(core, dependencies); this.metricVisualization.setup(core, dependencies); + this.pieVisualization.setup(core, dependencies); visualizations.registerAlias(getLensAliasConfig()); @@ -95,6 +99,7 @@ export class LensPlugin { this.createEditorFrame = this.editorFrameService.start(core, startDependencies).createInstance; this.xyVisualization.start(core, startDependencies); this.datatableVisualization.start(core, startDependencies); + this.pieVisualization.start(core, startDependencies); } stop() { diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx index 92a09f361230c..0f9aa1c10e127 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.test.tsx @@ -1178,5 +1178,135 @@ describe('xy_expression', () => { expect(convertSpy).toHaveBeenCalledWith('I'); }); + + test('it should remove invalid rows', () => { + const data: LensMultiTable = { + type: 'lens_multitable', + tables: { + first: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + ], + rows: [ + { a: undefined, b: 2, c: 'I', d: 'Row 1' }, + { a: 1, b: 5, c: 'J', d: 'Row 2' }, + ], + }, + second: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + ], + rows: [ + { a: undefined, b: undefined, c: undefined }, + { a: undefined, b: undefined, c: undefined }, + ], + }, + }, + }; + + const args: XYArgs = { + xTitle: '', + yTitle: '', + legend: { type: 'lens_xy_legendConfig', isVisible: false, position: Position.Top }, + layers: [ + { + layerId: 'first', + seriesType: 'line', + xAccessor: 'a', + accessors: ['c'], + splitAccessor: 'b', + columnToLabel: '', + xScaleType: 'ordinal', + yScaleType: 'linear', + isHistogram: false, + }, + { + layerId: 'second', + seriesType: 'line', + xAccessor: 'a', + accessors: ['c'], + splitAccessor: 'b', + columnToLabel: '', + xScaleType: 'ordinal', + yScaleType: 'linear', + isHistogram: false, + }, + ], + }; + + const component = shallow( + + ); + + const series = component.find(LineSeries); + + // Only one series should be rendered, even though 2 are configured + // This one series should only have one row, even though 2 are sent + expect(series.prop('data')).toEqual([{ a: 1, b: 5, c: 'J', d: 'Row 2' }]); + }); + + test('it should show legend for split series, even with one row', () => { + const data: LensMultiTable = { + type: 'lens_multitable', + tables: { + first: { + type: 'kibana_datatable', + columns: [ + { id: 'a', name: 'a' }, + { id: 'b', name: 'b' }, + { id: 'c', name: 'c' }, + ], + rows: [{ a: 1, b: 5, c: 'J' }], + }, + }, + }; + + const args: XYArgs = { + xTitle: '', + yTitle: '', + legend: { type: 'lens_xy_legendConfig', isVisible: true, position: Position.Top }, + layers: [ + { + layerId: 'first', + seriesType: 'line', + xAccessor: 'a', + accessors: ['c'], + splitAccessor: 'b', + columnToLabel: '', + xScaleType: 'ordinal', + yScaleType: 'linear', + isHistogram: false, + }, + ], + }; + + const component = shallow( + + ); + + expect(component.find(Settings).prop('showLegend')).toEqual(true); + }); }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx index 81ae57a5ee638..ab0af94cbc2b4 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/xy_expression.tsx @@ -181,7 +181,17 @@ export function XYChart({ }: XYChartRenderProps) { const { legend, layers } = args; - if (Object.values(data.tables).every(table => table.rows.length === 0)) { + const filteredLayers = layers.filter(({ layerId, xAccessor, accessors }) => { + return !( + !xAccessor || + !accessors.length || + !data.tables[layerId] || + data.tables[layerId].rows.length === 0 || + data.tables[layerId].rows.every(row => typeof row[xAccessor] === 'undefined') + ); + }); + + if (filteredLayers.length === 0) { const icon: IconType = layers.length > 0 ? getIconForSeriesType(layers[0].seriesType) : 'bar'; return ( @@ -198,16 +208,16 @@ export function XYChart({ } // use formatting hint of first x axis column to format ticks - const xAxisColumn = Object.values(data.tables)[0].columns.find( - ({ id }) => id === layers[0].xAccessor + const xAxisColumn = data.tables[filteredLayers[0].layerId].columns.find( + ({ id }) => id === filteredLayers[0].xAccessor ); const xAxisFormatter = formatFactory(xAxisColumn && xAxisColumn.formatHint); // use default number formatter for y axis and use formatting hint if there is just a single y column let yAxisFormatter = formatFactory({ id: 'number' }); - if (layers.length === 1 && layers[0].accessors.length === 1) { + if (filteredLayers.length === 1 && filteredLayers[0].accessors.length === 1) { const firstYAxisColumn = Object.values(data.tables)[0].columns.find( - ({ id }) => id === layers[0].accessors[0] + ({ id }) => id === filteredLayers[0].accessors[0] ); if (firstYAxisColumn && firstYAxisColumn.formatHint) { yAxisFormatter = formatFactory(firstYAxisColumn.formatHint); @@ -215,8 +225,10 @@ export function XYChart({ } const chartHasMoreThanOneSeries = - layers.length > 1 || data.tables[layers[0].layerId].columns.length > 2; - const shouldRotate = isHorizontalChart(layers); + filteredLayers.length > 1 || + filteredLayers.some(layer => layer.accessors.length > 1) || + filteredLayers.some(layer => layer.splitAccessor); + const shouldRotate = isHorizontalChart(filteredLayers); const xTitle = (xAxisColumn && xAxisColumn.name) || args.xTitle; @@ -311,7 +323,7 @@ export function XYChart({ const xySeries = series as XYChartSeriesIdentifier; const xyGeometry = geometry as GeometryValue; - const layer = layers.find(l => + const layer = filteredLayers.find(l => xySeries.seriesKeys.some((key: string | number) => l.accessors.includes(key.toString())) ); if (!layer) { @@ -366,7 +378,7 @@ export function XYChart({ position={shouldRotate ? Position.Left : Position.Bottom} title={xTitle} showGridLines={false} - hide={layers[0].hide} + hide={filteredLayers[0].hide} tickFormat={d => xAxisFormatter.convert(d)} /> @@ -375,11 +387,11 @@ export function XYChart({ position={shouldRotate ? Position.Bottom : Position.Left} title={args.yTitle} showGridLines={false} - hide={layers[0].hide} + hide={filteredLayers[0].hide} tickFormat={d => yAxisFormatter.convert(d)} /> - {layers.map( + {filteredLayers.map( ( { splitAccessor, @@ -394,16 +406,6 @@ export function XYChart({ }, index ) => { - if ( - !xAccessor || - !accessors.length || - !data.tables[layerId] || - data.tables[layerId].rows.length === 0 || - data.tables[layerId].rows.every(row => typeof row[xAccessor] === 'undefined') - ) { - return; - } - const columnToLabelMap: Record = columnToLabel ? JSON.parse(columnToLabel) : {}; @@ -414,12 +416,14 @@ export function XYChart({ // To not display them in the legend, they need to be filtered out. const rows = table.rows.filter( row => + xAccessor && + row[xAccessor] && !(splitAccessor && !row[splitAccessor] && accessors.every(accessor => !row[accessor])) ); const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], - stackAccessors: seriesType.includes('stacked') ? [xAccessor] : [], + stackAccessors: seriesType.includes('stacked') ? [xAccessor as string] : [], id: splitAccessor || accessors.join(','), xAccessor, yAccessors: accessors, diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts index 73ff88e97f479..722a07f581db5 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts @@ -11,7 +11,7 @@ import { DataType, TableSuggestion, } from '../types'; -import { State, XYState } from './types'; +import { State, XYState, visualizationTypes } from './types'; import { generateId } from '../id_generator'; jest.mock('../id_generator'); @@ -106,7 +106,68 @@ describe('xy_suggestions', () => { ); }); - test('suggests a basic x y chart with date on x', () => { + test('suggests all basic x y charts when switching from another vis', () => { + (generateId as jest.Mock).mockReturnValueOnce('aaa'); + const suggestions = getSuggestions({ + table: { + isMultiRow: true, + columns: [numCol('bytes'), dateCol('date')], + layerId: 'first', + changeType: 'unchanged', + }, + keptLayerIds: [], + }); + + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions.map(({ state }) => state.preferredSeriesType)).toEqual([ + 'bar_stacked', + 'area_stacked', + 'area', + 'line', + 'bar_horizontal_stacked', + 'bar_horizontal', + 'bar', + ]); + }); + + test('suggests all basic x y charts when switching from another x y chart', () => { + (generateId as jest.Mock).mockReturnValueOnce('aaa'); + const suggestions = getSuggestions({ + table: { + isMultiRow: true, + columns: [numCol('bytes'), dateCol('date')], + layerId: 'first', + changeType: 'unchanged', + }, + keptLayerIds: ['first'], + state: { + legend: { isVisible: true, position: 'bottom' }, + preferredSeriesType: 'bar', + layers: [ + { + layerId: 'first', + seriesType: 'bar', + xAccessor: 'date', + accessors: ['bytes'], + splitAccessor: undefined, + }, + ], + }, + }); + + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions.map(({ state }) => state.preferredSeriesType)).toEqual([ + 'line', + 'bar', + 'bar_horizontal', + 'bar_stacked', + 'bar_horizontal_stacked', + 'area', + 'area_stacked', + ]); + }); + + test('suggests all basic x y chart with date on x', () => { (generateId as jest.Mock).mockReturnValueOnce('aaa'); const [suggestion, ...rest] = getSuggestions({ table: { @@ -118,7 +179,7 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - expect(rest).toHaveLength(0); + expect(rest).toHaveLength(visualizationTypes.length - 1); expect(suggestionSubset(suggestion)).toMatchInlineSnapshot(` Array [ Object { @@ -164,7 +225,7 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - expect(rest).toHaveLength(0); + expect(rest).toHaveLength(visualizationTypes.length - 1); expect(suggestionSubset(suggestion)).toMatchInlineSnapshot(` Array [ Object { @@ -208,8 +269,8 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - expect(rest).toHaveLength(0); - expect(suggestion.title).toEqual('Bar chart'); + expect(rest).toHaveLength(visualizationTypes.length - 1); + expect(suggestion.title).toEqual('Stacked bar'); expect(suggestion.state).toEqual( expect.objectContaining({ layers: [ @@ -267,7 +328,7 @@ describe('xy_suggestions', () => { expect(suggestion.hide).toBeTruthy(); }); - test('only makes a seriesType suggestion for unchanged table without split', () => { + test('makes a visible seriesType suggestion for unchanged table without split', () => { const currentState: XYState = { legend: { isVisible: true, position: 'bottom' }, preferredSeriesType: 'bar', @@ -292,8 +353,9 @@ describe('xy_suggestions', () => { keptLayerIds: ['first'], }); - expect(suggestions).toHaveLength(1); + expect(suggestions).toHaveLength(visualizationTypes.length); + expect(suggestions[0].hide).toEqual(false); expect(suggestions[0].state).toEqual({ ...currentState, preferredSeriesType: 'line', @@ -327,7 +389,7 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - expect(rest).toHaveLength(0); + expect(rest).toHaveLength(visualizationTypes.length - 2); expect(seriesSuggestion.state).toEqual({ ...currentState, preferredSeriesType: 'line', @@ -368,7 +430,7 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - expect(rest).toHaveLength(0); + expect(rest).toHaveLength(visualizationTypes.length - 1); expect(suggestion.state.preferredSeriesType).toEqual('bar_horizontal'); expect(suggestion.state.layers.every(l => l.seriesType === 'bar_horizontal')).toBeTruthy(); expect(suggestion.title).toEqual('Flip'); @@ -399,14 +461,13 @@ describe('xy_suggestions', () => { keptLayerIds: [], }); - const suggestion = suggestions[suggestions.length - 1]; - - expect(suggestion.state).toEqual({ - ...currentState, - preferredSeriesType: 'bar_stacked', - layers: [{ ...currentState.layers[0], seriesType: 'bar_stacked' }], - }); - expect(suggestion.title).toEqual('Stacked'); + const visibleSuggestions = suggestions.filter(suggestion => !suggestion.hide); + expect(visibleSuggestions).toContainEqual( + expect.objectContaining({ + title: 'Stacked', + state: expect.objectContaining({ preferredSeriesType: 'bar_stacked' }), + }) + ); }); test('keeps column to dimension mappings on extended tables', () => { diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts index abd7640344064..71cb8e0cbdc99 100644 --- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts +++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts @@ -14,7 +14,7 @@ import { TableSuggestion, TableChangeType, } from '../types'; -import { State, SeriesType, XYState } from './types'; +import { State, SeriesType, XYState, visualizationTypes } from './types'; import { getIconForSeries } from './state_helpers'; const columnSortOrder = { @@ -180,14 +180,14 @@ function getSuggestionsForLayer({ // handles the simplest cases, acting as a chart switcher if (!currentState && changeType === 'unchanged') { - return [ - { - ...buildSuggestion(options), - title: i18n.translate('xpack.lens.xySuggestions.barChartTitle', { - defaultMessage: 'Bar chart', - }), - }, - ]; + // Chart switcher needs to include every chart type + return visualizationTypes + .map(visType => ({ + ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), + title: visType.label, + hide: visType.id !== 'bar_stacked', + })) + .sort((a, b) => (a.state.preferredSeriesType === 'bar_stacked' ? -1 : 1)); } const isSameState = currentState && changeType === 'unchanged'; @@ -248,7 +248,21 @@ function getSuggestionsForLayer({ ); } - return sameStateSuggestions; + // Combine all pre-built suggestions with hidden suggestions for remaining chart types + return sameStateSuggestions.concat( + visualizationTypes + .filter(visType => { + return !sameStateSuggestions.find( + suggestion => suggestion.state.preferredSeriesType === visType.id + ); + }) + .map(visType => { + return { + ...buildSuggestion({ ...options, seriesType: visType.id as SeriesType }), + hide: true, + }; + }) + ); } function toggleStackSeriesType(oldSeriesType: SeriesType) { From e344adb5724bfd30381af0f56d1db9c4eff027d6 Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Tue, 5 May 2020 13:42:21 -0700 Subject: [PATCH 37/72] Remove events.module from query, use dataset string or index name instead (#65328) --- .../server/routes/data_streams/handlers.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts index ad81076e34e4b..80a33c26d86da 100644 --- a/x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/data_streams/handlers.ts @@ -70,12 +70,6 @@ export const getListHandler: RequestHandler = async (context, request, response) size: 1, }, }, - package: { - terms: { - field: 'event.module', - size: 1, - }, - }, last_activity: { max: { field: '@timestamp', @@ -110,11 +104,15 @@ export const getListHandler: RequestHandler = async (context, request, response) dataset: { buckets: datasetBuckets }, namespace: { buckets: namespaceBuckets }, type: { buckets: typeBuckets }, - package: { buckets: packageBuckets }, last_activity: { value_as_string: lastActivity }, } = result; - const pkg = packageBuckets.length ? packageBuckets[0].key : ''; + // We don't have a reliable way to associate index with package ID, so + // this is a hack to extract the package ID from the first part of the dataset name + // with fallback to extraction from index name + const pkg = datasetBuckets.length + ? datasetBuckets[0].key.split('.')[0] + : indexName.split('-')[1].split('.')[0]; const pkgSavedObject = packageSavedObjects.saved_objects.filter(p => p.id === pkg); // if From ea19374a21ee4faa18ddff86ef4e0177624d7f7d Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Tue, 5 May 2020 13:44:39 -0700 Subject: [PATCH 38/72] [Ingest] Enforce security required and superuser permissions (#65315) * Add check permissions route and request hook * Conditionally register routes * Add security not enabled and permissions missing warning UIs * Hide global settings when there is an error --- .../ingest_manager/common/constants/routes.ts | 5 + .../ingest_manager/common/services/routes.ts | 5 + .../common/types/rest_spec/app.ts | 10 + .../common/types/rest_spec/index.ts | 1 + .../ingest_manager/hooks/use_request/app.ts | 16 ++ .../ingest_manager/hooks/use_request/index.ts | 1 + .../applications/ingest_manager/index.tsx | 211 +++++++++++++----- .../ingest_manager/layouts/default.tsx | 25 ++- .../ingest_manager/services/index.ts | 1 + .../ingest_manager/types/index.ts | 2 + .../plugins/ingest_manager/public/plugin.ts | 11 +- .../ingest_manager/server/constants/index.ts | 1 + .../plugins/ingest_manager/server/plugin.ts | 46 ++-- .../ingest_manager/server/routes/app/index.ts | 44 ++++ .../ingest_manager/server/routes/index.ts | 1 + 15 files changed, 286 insertions(+), 94 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts create mode 100644 x-pack/plugins/ingest_manager/server/routes/app/index.ts diff --git a/x-pack/plugins/ingest_manager/common/constants/routes.ts b/x-pack/plugins/ingest_manager/common/constants/routes.ts index 35e3be98e3982..abb266da9f066 100644 --- a/x-pack/plugins/ingest_manager/common/constants/routes.ts +++ b/x-pack/plugins/ingest_manager/common/constants/routes.ts @@ -61,6 +61,11 @@ export const SETTINGS_API_ROUTES = { UPDATE_PATTERN: `${API_ROOT}/settings`, }; +// App API routes +export const APP_API_ROUTES = { + CHECK_PERMISSIONS_PATTERN: `${API_ROOT}/check-permissions`, +}; + // Agent API routes export const AGENT_API_ROUTES = { LIST_PATTERN: `${FLEET_API_ROOT}/agents`, diff --git a/x-pack/plugins/ingest_manager/common/services/routes.ts b/x-pack/plugins/ingest_manager/common/services/routes.ts index 1a1bd7c65aa25..20d040ac6eaee 100644 --- a/x-pack/plugins/ingest_manager/common/services/routes.ts +++ b/x-pack/plugins/ingest_manager/common/services/routes.ts @@ -15,6 +15,7 @@ import { SETUP_API_ROUTE, OUTPUT_API_ROUTES, SETTINGS_API_ROUTES, + APP_API_ROUTES, } from '../constants'; export const epmRouteService = { @@ -126,6 +127,10 @@ export const settingsRoutesService = { getUpdatePath: () => SETTINGS_API_ROUTES.UPDATE_PATTERN, }; +export const appRoutesService = { + getCheckPermissionsPath: () => APP_API_ROUTES.CHECK_PERMISSIONS_PATTERN, +}; + export const enrollmentAPIKeyRouteService = { getListPath: () => ENROLLMENT_API_KEY_ROUTES.LIST_PATTERN, getCreatePath: () => ENROLLMENT_API_KEY_ROUTES.CREATE_PATTERN, diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts new file mode 100644 index 0000000000000..b3a1a46fc54ef --- /dev/null +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/app.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export interface CheckPermissionsResponse { + error?: 'MISSING_SECURITY' | 'MISSING_SUPERUSER_ROLE'; + success: boolean; +} diff --git a/x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts b/x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts index 763fb7d820b2a..eb212050ef53e 100644 --- a/x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts +++ b/x-pack/plugins/ingest_manager/common/types/rest_spec/index.ts @@ -14,3 +14,4 @@ export * from './enrollment_api_key'; export * from './install_script'; export * from './output'; export * from './settings'; +export * from './app'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts new file mode 100644 index 0000000000000..713535acbabca --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/app.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { sendRequest } from './use_request'; +import { appRoutesService } from '../../services'; +import { CheckPermissionsResponse } from '../../types'; + +export const sendGetPermissionsCheck = () => { + return sendRequest({ + path: appRoutesService.getCheckPermissionsPath(), + method: 'get', + }); +}; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts index 25cdffc5c6651..8aec20d15c888 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_request/index.ts @@ -13,3 +13,4 @@ export * from './epm'; export * from './outputs'; export * from './settings'; export * from './setup'; +export * from './app'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx index f0a0c90a18c24..3612497e723cd 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx @@ -7,8 +7,10 @@ import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom'; import { useObservable } from 'react-use'; import { HashRouter as Router, Redirect, Switch, Route, RouteProps } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiErrorBoundary } from '@elastic/eui'; +import styled from 'styled-components'; +import { EuiErrorBoundary, EuiPanel, EuiEmptyPrompt, EuiCode } from '@elastic/eui'; import { CoreStart, AppMountParameters } from 'src/core/public'; import { EuiThemeProvider } from '../../../../../legacy/common/eui_styled_components'; import { @@ -22,7 +24,7 @@ import { Loading, Error } from './components'; import { IngestManagerOverview, EPMApp, AgentConfigApp, FleetApp, DataStreamApp } from './sections'; import { CoreContext, DepsContext, ConfigContext, setHttpClient, useConfig } from './hooks'; import { PackageInstallProvider } from './sections/epm/hooks'; -import { sendSetup } from './hooks/use_request/setup'; +import { useCore, sendSetup, sendGetPermissionsCheck } from './hooks'; import { FleetStatusProvider } from './hooks/use_fleet_status'; import './index.scss'; @@ -39,86 +41,175 @@ export const ProtectedRoute: React.FunctionComponent = ({ return isAllowed ? : ; }; +const Panel = styled(EuiPanel)` + max-width: 500px; + margin-right: auto; + margin-left: auto; +`; + +const ErrorLayout = ({ children }: { children: JSX.Element }) => ( + + + {children} + + +); + const IngestManagerRoutes = ({ ...rest }) => { const { epm, fleet } = useConfig(); + const { notifications } = useCore(); + const [isPermissionsLoading, setIsPermissionsLoading] = useState(false); + const [permissionsError, setPermissionsError] = useState(); const [isInitialized, setIsInitialized] = useState(false); const [initializationError, setInitializationError] = useState(null); useEffect(() => { (async () => { + setIsPermissionsLoading(false); + setPermissionsError(undefined); setIsInitialized(false); setInitializationError(null); try { - const res = await sendSetup(); - if (res.error) { - setInitializationError(res.error); + setIsPermissionsLoading(true); + const permissionsResponse = await sendGetPermissionsCheck(); + setIsPermissionsLoading(false); + if (permissionsResponse.data?.success) { + try { + const setupResponse = await sendSetup(); + if (setupResponse.error) { + setInitializationError(setupResponse.error); + } + } catch (err) { + setInitializationError(err); + } + setIsInitialized(true); + } else { + setPermissionsError(permissionsResponse.data?.error || 'REQUEST_ERROR'); } } catch (err) { - setInitializationError(err); + setPermissionsError('REQUEST_ERROR'); } - setIsInitialized(true); })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + if (isPermissionsLoading || permissionsError) { + return ( + + {isPermissionsLoading ? ( + + ) : permissionsError === 'REQUEST_ERROR' ? ( + + } + error={i18n.translate('xpack.ingestManager.permissionsRequestErrorMessageDescription', { + defaultMessage: 'There was a problem checking Ingest Manager permissions', + })} + /> + ) : ( + + + {permissionsError === 'MISSING_SUPERUSER_ROLE' ? ( + + ) : ( + + )} +

+ } + body={ +

+ {permissionsError === 'MISSING_SUPERUSER_ROLE' ? ( + superuser }} + /> + ) : ( + + )} +

+ } + /> + + )} + + ); + } + if (!isInitialized || initializationError) { return ( - - - - {initializationError ? ( - - } - error={initializationError} + + {initializationError ? ( + - ) : ( - - )} - - - + } + error={initializationError} + /> + ) : ( + + )} + ); } return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); }; @@ -142,11 +233,7 @@ const IngestManagerApp = ({ - - - - - + diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 4a9cfe02b74ac..e9d7fcb1cf5c5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -13,6 +13,7 @@ import { useLink, useConfig } from '../hooks'; import { EPM_PATH, FLEET_PATH, AGENT_CONFIG_PATH, DATA_STREAM_PATH } from '../constants'; interface Props { + showSettings?: boolean; section?: Section; children?: React.ReactNode; } @@ -33,7 +34,11 @@ const Nav = styled.nav` } `; -export const DefaultLayout: React.FunctionComponent = ({ section, children }) => { +export const DefaultLayout: React.FunctionComponent = ({ + showSettings = true, + section, + children, +}) => { const { epm, fleet } = useConfig(); const [isSettingsFlyoutOpen, setIsSettingsFlyoutOpen] = React.useState(false); @@ -109,14 +114,16 @@ export const DefaultLayout: React.FunctionComponent = ({ section, childre />
- - setIsSettingsFlyoutOpen(true)}> - - - + {showSettings ? ( + + setIsSettingsFlyoutOpen(true)}> + + + + ) : null}
diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts index e4791cc816d04..64669b5cd123a 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/services/index.ts @@ -17,6 +17,7 @@ export { setupRouteService, outputRoutesService, settingsRoutesService, + appRoutesService, packageToConfigDatasourceInputs, storedDatasourceToAgentDatasource, AgentStatusKueryHelper, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts index ca5bf999aa81a..0a26a16d35cfd 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/types/index.ts @@ -62,6 +62,8 @@ export { GetSettingsResponse, PutSettingsRequest, PutSettingsResponse, + // API schemas - app + CheckPermissionsResponse, // EPM types AssetReference, AssetsGroupedByServiceByType, diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index 77bba0bb0f990..90d82cf609d10 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -17,7 +17,7 @@ import { LicensingPluginSetup } from '../../licensing/public'; import { PLUGIN_ID } from '../common/constants'; import { IngestManagerConfigType } from '../common/types'; -import { setupRouteService } from '../common'; +import { setupRouteService, appRoutesService } from '../common'; export { IngestManagerConfigType } from '../common/types'; @@ -72,8 +72,13 @@ export class IngestManagerPlugin public async start(core: CoreStart): Promise { try { - const { isInitialized: success } = await core.http.post(setupRouteService.getSetupPath()); - return { success }; + const permissionsResponse = await core.http.get(appRoutesService.getCheckPermissionsPath()); + if (permissionsResponse.success) { + const { isInitialized: success } = await core.http.post(setupRouteService.getSetupPath()); + return { success }; + } else { + throw new Error(permissionsResponse.error); + } } catch (error) { return { success: false, error: { message: error.body?.message || 'Unknown error' } }; } diff --git a/x-pack/plugins/ingest_manager/server/constants/index.ts b/x-pack/plugins/ingest_manager/server/constants/index.ts index 75c14ffc8fa84..3468c56cc877f 100644 --- a/x-pack/plugins/ingest_manager/server/constants/index.ts +++ b/x-pack/plugins/ingest_manager/server/constants/index.ts @@ -22,6 +22,7 @@ export { OUTPUT_API_ROUTES, SETUP_API_ROUTE, SETTINGS_API_ROUTES, + APP_API_ROUTES, // Saved object types AGENT_SAVED_OBJECT_TYPE, AGENT_EVENT_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/ingest_manager/server/plugin.ts b/x-pack/plugins/ingest_manager/server/plugin.ts index d70e136d67ef5..24f3a11789dc7 100644 --- a/x-pack/plugins/ingest_manager/server/plugin.ts +++ b/x-pack/plugins/ingest_manager/server/plugin.ts @@ -42,6 +42,7 @@ import { registerInstallScriptRoutes, registerOutputRoutes, registerSettingsRoutes, + registerAppRoutes, } from './routes'; import { IngestManagerConfigType } from '../common'; import { @@ -164,26 +165,31 @@ export class IngestManagerPlugin const router = core.http.createRouter(); const config = await this.config$.pipe(first()).toPromise(); - // Register routes - registerSetupRoutes(router, config); - registerAgentConfigRoutes(router); - registerDatasourceRoutes(router); - registerOutputRoutes(router); - registerSettingsRoutes(router); - registerDataStreamRoutes(router); - - // Conditional routes - if (config.epm.enabled) { - registerEPMRoutes(router); - } - - if (config.fleet.enabled) { - registerAgentRoutes(router); - registerEnrollmentApiKeyRoutes(router); - registerInstallScriptRoutes({ - router, - basePath: core.http.basePath, - }); + // Always register app routes for permissions checking + registerAppRoutes(router); + + // Register rest of routes only if security is enabled + if (this.security) { + registerSetupRoutes(router, config); + registerAgentConfigRoutes(router); + registerDatasourceRoutes(router); + registerOutputRoutes(router); + registerSettingsRoutes(router); + registerDataStreamRoutes(router); + + // Conditional config routes + if (config.epm.enabled) { + registerEPMRoutes(router); + } + + if (config.fleet.enabled) { + registerAgentRoutes(router); + registerEnrollmentApiKeyRoutes(router); + registerInstallScriptRoutes({ + router, + basePath: core.http.basePath, + }); + } } } diff --git a/x-pack/plugins/ingest_manager/server/routes/app/index.ts b/x-pack/plugins/ingest_manager/server/routes/app/index.ts new file mode 100644 index 0000000000000..9d666efc7e9ce --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/routes/app/index.ts @@ -0,0 +1,44 @@ +/* + * 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 { IRouter, RequestHandler } from 'src/core/server'; +import { PLUGIN_ID, APP_API_ROUTES } from '../../constants'; +import { appContextService } from '../../services'; +import { CheckPermissionsResponse } from '../../../common'; + +export const getCheckPermissionsHandler: RequestHandler = async (context, request, response) => { + const body: CheckPermissionsResponse = { success: true }; + try { + const security = await appContextService.getSecurity(); + const user = security.authc.getCurrentUser(request); + + if (!user?.roles.includes('superuser')) { + body.success = false; + body.error = 'MISSING_SUPERUSER_ROLE'; + return response.ok({ + body, + }); + } + + return response.ok({ body: { success: true } }); + } catch (e) { + body.success = false; + body.error = 'MISSING_SECURITY'; + return response.ok({ + body, + }); + } +}; + +export const registerRoutes = (router: IRouter) => { + router.get( + { + path: APP_API_ROUTES.CHECK_PERMISSIONS_PATTERN, + validate: {}, + options: { tags: [`access:${PLUGIN_ID}-read`] }, + }, + getCheckPermissionsHandler + ); +}; diff --git a/x-pack/plugins/ingest_manager/server/routes/index.ts b/x-pack/plugins/ingest_manager/server/routes/index.ts index 3ce34d15de46c..0978c2aa57bf6 100644 --- a/x-pack/plugins/ingest_manager/server/routes/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/index.ts @@ -13,3 +13,4 @@ export { registerRoutes as registerEnrollmentApiKeyRoutes } from './enrollment_a export { registerRoutes as registerInstallScriptRoutes } from './install_script'; export { registerRoutes as registerOutputRoutes } from './output'; export { registerRoutes as registerSettingsRoutes } from './settings'; +export { registerRoutes as registerAppRoutes } from './app'; From 43021611122701413b5ba4832f3148fdd1952149 Mon Sep 17 00:00:00 2001 From: IgorG <56408662+IgorGuz2000@users.noreply.github.com> Date: Tue, 5 May 2020 13:50:00 -0700 Subject: [PATCH 39/72] New resolver (#64704) * New commit * New commit adding data-test-subj to controls * Final commit for the resolver tests * Final commit for the resolver tests * Final commit for the resolver tests * Final commit for the resolver tests * Final commit for the resolver tests * Removed sleep statements and added "WaitForTableToHaveData" * Removed sleep statements and added "WaitForTableToHaveData" * Fixed type check and modified style parsing * Removed window resize * Fixed style type errors * Removed unnecessary sleeps and added verifications for Nodes location * Removed unnecessary sleeps and added verifications for Nodes location * Merge branch 'master' of https://github.com/elastic/kibana into new_resolver * Merge branch 'master' of https://github.com/elastic/kibana into new_resolver * Merge branch 'master' of https://github.com/elastic/kibana into new_resolver * Added resize the window for PAss the test * Added resize the window for PAss the test * Added resize the window for PAss the test * Added resize the window for PAss the test * Added resize the window for PAss the test Co-authored-by: Elastic Machine --- .../resolver/view/graph_controls.tsx | 40 +- .../resolver/view/process_event_dot.tsx | 4 +- .../resolver_tree/api_feature/data.json.gz | Bin 0 -> 24261 bytes .../resolver_tree/api_feature/mappings.json | 2906 +++++++++++++++++ .../apps/endpoint/index.ts | 1 + .../apps/endpoint/resolver.ts | 259 ++ .../page_objects/endpoint_alerts_page.ts | 99 +- 7 files changed, 3300 insertions(+), 9 deletions(-) create mode 100644 x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/data.json.gz create mode 100644 x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/mappings.json create mode 100644 x-pack/test/functional_endpoint/apps/endpoint/resolver.ts diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx index a1cd003949a22..32c3f73ced287 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/graph_controls.tsx @@ -85,40 +85,66 @@ export const GraphControls = styled(
-
- - -
-
- - diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx index 3201e83164dba..0840b990ea315 100644 --- a/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx +++ b/x-pack/plugins/endpoint/public/embeddables/resolver/view/process_event_dot.tsx @@ -351,7 +351,9 @@ export const ProcessEventDot = styled( }} > - {eventModel.eventName(event)} + + {eventModel.eventName(event)} +
{magFactorX >= 2 && ( diff --git a/x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/data.json.gz b/x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..7974eaf35041dc93196a97cd6ba092648a16f790 GIT binary patch literal 24261 zcmdSARa9JGyY3kXt_7j6!U}hHcX#*T?(PJ42^8)w!68T>1b24}8Z40D7OWxv{e8Xn z?%jRH=!-MP;i9hATx-oaU->=Hnh?hzym|eDes}zJ)dM7zRPHaN6jWjxK{*-G`G*JJ zyT$TT`&R~c-v>u;>)nqqhycJFBFnq)o>AU z7Q>VNV;g*NY*~L(kS%wT|%{4<6}H zrU5>#1J;ab<1)J)*%PJ8iWgpULOD?1_)K|uvx@I+x2c{ts)Xogb#UX))M|1}WM!;T z(uCG>FwxFzkT>q;QZZ%KDJ;stKxG;2$Y?w#N*W^Q#`u05p|!xH4*Al@Y3mD(3)Rj` zCI|G#vqMb^g*3;eQ{a>8S2IwjOXtEDEQ?(y_BNYNj@($)3`LwQ=UK0DbwyRzDOD?F z-XE(2IKVJDN$ig}-`s=0-d8x{ps#&xVW%-(XmYQPk}5isMb1)E>~(tj`fd9Juw6%l znk>kp=V-0Ua)CwXbi`1u&+YXQ24S}<*3f2uX{IGp>n>2}F)q*PI*ILJvLQ`$In32D z!TC;=`C+n_(B-^jhpCN~Ns#c?e@nABQS+ok1(V+iwm;+ou)OCOpZcCXKy?x>WY0OU zKc2`y-q&#yW+Om}nK3oXebE`Gg(@?Rjw(AsMrbU|WY>hQj3K(H)p3v5mg!V6GIbps zEfVN)wY5iR5PMf;#ikshRQtT~JK*WeG4Nsa+v6lQtsofaDA8Yp)Ln0vZx%tDYZp!u z3bpHk6st9NE>5dR`@{{LEaTK4xF~Wq@O!tztOJ~2YBVl@QYs7m4ohKoLt`AwsRKeU z^@_KXwn8ZW&{JKsqwk$uNg)fMAd*7l%0d&$wB;mnl!=1vXp)XP;%d(iJrbmdu2-aB z=x&XKM5aPzVgub&GPVNarKBJvvi$LwTgS((n%+Dvda5Q+O!lgz9vPV4jMO)(EpzSG zkkJV1=Tr8v2}<*lldK57m_dqh!8MubPoK1vUCWAQ*OkhwWkfT7=VmKdmUyE*RMQjO z??miop$$HY+)cU7c0?4bmRn~tHDyxbn@=7P<1_*osjz(EIsmfB3)&GyE&D3VZ3v29xxPNaocfGEu_r<9*21 z>cwS)eyTZt92bIPdU2`iOtsawR(6}uF@Ji`sQngISf z_^g5_+dz*w-|vYPfj+l@WUknI@b~D&N9~7Ri%*-H%sA-#%*eB>#O#6sCtqwoR!@xZ zCDMdt;hHAO2VwL25F)9`h0IeGfl)@x4qbXx1VNC=@5iH*62H(#e)e*S%@JsTpdKmM zYl2w9*K8FH2{}(bYWEuXO!f(3pUkm8bT``>Z4n~ca?^a>gYq4Rm%HfliI$p`IZ4mqLawdIJ2aK9q{2)&!gvyY0fAPDTWAb6^ z`lDw0xrv*z&+J3Xx3B&;e;h|sM+lpr9t-H!NR?>qvHL%x3=(GsJk>d6?DbyRezfnv zX+HZceSttnu*;Y;F50oh5WQy^dM_vKlP>ulW?Bs8%Td&7>J=j;_lQ#Gv25)AN%e)7|gd=iA*f&u^S3DLFW^JJb0oL#g_>G0?DSRym8Q>-&D2R+H2naufxg^F-|T7s9e zHflUC?1ZWU+Os)b&Sd%);x|5@+w-JzlK#0U7D7q>+k1h2S)b>UnHY zzij5`2iI&y1G`{!lUCA3AZ55%ag7NvB7}H3(-bY1vka!n$h{U>Eae7cmIalbxtKhW z#h6?GFOU3eDIwm9H=VL&-c2l;g)l1HA0e%RS!lJ(%b(RIgE8%JE_9+#x~n{|K6>Lo z>CtBn@I@+8AdFd)b=Z@B5JxQR+o3k5lA4thz$eUPpsD|m#z})QoVpZ_d2xE0xxGB} zd6#-b<`hL%_w6**TN$5}>f~GfOn^w_E#r4oPO!LLNaQSQJFbEvCqpdFuz3i+B`H2; zJiJp4OdV;Vc;<7o*qieB5L+;KfFuZH9LvBX zU5$VV6Lo@#`G6`?2viHk!`5*}$u>tML?cqUDGVhwvqLjCw4xAH+2$*O=_l7M6p!U# zjdRgg&P|D2y49s^)z4^dfXf(8C6VoI|R*KiMZlC%wtuLs*u$s3^HjG_{~r9{+{C3iKBbqx8lb~GlJQtC#K9T!u5^kU1bT7%o}nF zsC@D_diVK!8CU1u6V$yYUHdsh#=E)B?AW>5xVX2smVQ*8N=*6q;>Qx>Rb&qB6gdl_ zxURXl>EP<=#i|b*jQRYHLtSJw(%CM3hvpl6Sdp+d-M-+j@vJ(!vU0Dh3&&Rd2o@sD z5kQwcHd&B6`>hrX)C``%N8+m25lL1lOnFn5Ju-&#-j3vN>x&X|^~arHO8B#?YSNAH zGV%8GD^(M8yQo;S@I(y1>&{`5tT&(IL@;?m35sgR0I$odZ;3On1y&fdE@ZQd~XuA`?CFC@ED@{nCq_(d1>TRlLiv50Y7sB^iAa^y_D! z8Q7G1aF>!%h3qzowRlsVA^UDK3iEYHk2vx7rI_Aid(Z1Nc=nazKE-WJ-@50?voV7T zM16be?&`O-9dNcbs_~5gH_CrFA@FznpF1zV^D`Y~(GzmUdieWiGiC+sSrk@DyN(pt z>`Tm8q_D-R!jvY%VCpkz*=zzLo8jWPRcxsD2)@lSQ8|4S*G9ie+=eASy*o{}X{@CE zfDA6smO4@EA~tC+L|j^hLC{scvSccsX-AMb5YYC>=xCy+L0#tLBa9g<_e~8#oi9Si ztVRxgBl6*PeL?lmK%DH7sH#<7v<`E+y^dd|D?;)+a{n8-{v&nqM9Oz02!M@MXvD@C z;n4Mv{!|*Dvg(gUbWh6tMV{cwt_^LE`E-0NsNgqe->c)8+apC@9%-4Ox*!jM?$MbO zz#$X2gt3|gU`bS#lf7Q`l_7?iFG}RN8&i(KB$1aELF2-LwpV0`LpWYXdq*6SLXQC5 z=h;Hqb4(6bkN$}+1{qHPk$I)T!rfd1hl~=i&I{JZjCO^Ff!g-fLowc%YCg4p!*Vb< z?9!9Z_Z>O>h;+(}8O1%p(#{WnBC7J)!jQwX3HN0w{U_XYWr^y66oPsY3KaGYv`}s) zP!Lx$>jl*xu}$+=7l!>>C736CStH5%5Ub$GtXpzPT6c( zbhWoAFV$ZB#CJ?3JectN8!mVid{)SxpU#^kpSViV!h2Xh=_@y~# zL~hFC?9{T&Y*zBpevmF?wFzZ3|KL7PB*bW$rlw-qiY{-CO@)bZ3&sbAG$cwnDg_z& z71r4Mp*)ap>nFKKayUfn7@%;eI1ix#fdvz zOS1e&7j8tUxRr;GchpmaT48!7YgtpvOBcbyJPjwAp12IBSCvcavUo4T^Q&7Aqss{h z0SaP^eQJ#QJH-NXK4Zk;*6kVFa#D#V3b#;_hR_4kRQ@(<$ZL*uD#PdyNOIF11LjajtDV5^%w*!fr(1q_{ z-O9V~P3(&qc3x7PDz%m0l**Wuhu`OHp7v=AwZe;z_P1)1gq-?uj{vQr`li20Vp6;) zTure`@pkccg4)?~#m-_;@4@!Jx{YApKiwutqC2NaIm~uDek6EuI%xQd3Dr=x4fvlD z+Uv#t$%9#7nNw;P+VG{2nBhR2zL$ljlw@kZom(pIo)isAUh+yNY#hcifNev5Ej}h* ztb)9r#|NTzS;N;vFY2M^f0ueFR>GWt9VZ-}rXAPP;}k%8pj6A96&>yq<>=lNFhvsq zS!63_rl~d#v($HN-Fr2*X#xL_RuB5;o{oQ9xI0rCabz0kr|>=abt;fLSuCTe3$X{( zEc_~{77i}%9|68{k>(X+;b^@jENvwP{~M~^wPj>q5D z-ec3c=(WL zH9&}u6r435|3gD?on*Xf2=xAcYlsh9gh>BcLlpf>Ls0x%L&#P$|J4wXYc%Co4RQ9W zAu_IxgyuUEj+sTZfU&L{B@=#)H_+e8v!V9y3av&VMd(+I9`!nY^ zo?k-(JMWK#0`3mKJC2SE>!IrN4vZh;p`QhE z995?)DBO>*EBx8vyWdP>CCcZTLH??D_-ov8vE93wSo52KB53Q5Ji>PHME9N z|t3+NdpxOiLuwucvaB?!_tZBn+PvWYSR)VFCj)7{(##RAcSPSaD0Hp)XG> z^m*TMP-@izsBbC;>OKe=W~4T5SBj$j8p{eRt*d3{7fU@iFTAZGUhru@yR_)qQ5LmGP|XsSYsfZyOIn-G)Ia`Q|dYy6{&qW_!X`~MrTJG zi;z7!?NRst`W??+v*xl>eVht*v#&pa0VbgORsGss9s83a#u9F7ek6ijr}CKQ}rKm(U ztgE@8%*Kd8%k|cx_xSnKau3G`V`&e|WiT~vdv;z9=OqpzhYU3Se6o}N%5bYW;%aA- zMFim%wiX!ju!lUe^dD!EXM{8krIL4^4k`nAi5#rWYGw=Ltgb$BwQq+166C5{l;>-D zXTxko%C5A@x`H;s=Mdx8LnE?A;=sSG{h}PRFDKod^ju7#xb0oYeg}hU?$;7mD$`Sf z%2g79Y}kodP^}e)L*<2xNv$GlUbI|(<%gGJN+S!`0|HJfKL(0N*YcO0GYQLHf1V$X zZ>{uoH_m?PU?||*0J3?Mm#qlWUHgKRoaU59V*?ENI^(;f288CfoA$zg>Ilexy&~ zne&+;vJyUm(7b4niWV@Iy+wYDu=;MN{g@kp-%2Y7eo@>A;#}?$Nw!x}I zk932~OGq66T)88t>cwOpUb>fVat`#kv4~QH}?{UBxm;L=`Z!S%y%5zqKjq8Z?q& zHHc#i|7Xkq{h698MNM=7(b|%XpD8*gv(J0k)B5Ge;!ORuf{b8}3#6tsSDg+NKRO2^ z$9JpSYBKT*|x@8y))he60wiDi6TR{Peu4bzsW1N zuEAWgpGR;I0}Ri|ib#2P1<12vJ?Z;@;DSRE&mQ5~17e$|Y(Zw(smuLVE)6wty3FRX zbCD=%%1fU^NUETWixOf%8f@m8U=$%bL4r5$|wIC3frH1XTBShp`9E30cV&-%yiQd*vt{0g) zKw^Kw`6X!$g|9mD3V>*(!6Hny=v) zo1TZF_DD)`);%)GEm@fph1sSg;x6fS<54HWg#O^b#c-inFKQEs;*10tYz@5M0C4GM zNS*1!vop{_A}69ol7eoA3!2*TWm!c)axZ!776$s*T93*_xmzccV-Fo+|8tAHKkKvM zLHR8{*d?v&3{vGpu_q4)A5_G)nSU#Z>`K$W`va>mxc&n}nw5Q@Dl+@wW=^^4fbgmz zB7RO#c*(Ex_vmq%a+qzh2wylE1~>Sb;2Jo<=f^I)SeO)6ZsuGgN)Xeclnktd%<>o) zfVnul1R@kz8ksb7Gid>jFZiDYAT=&ZL0sClZ%7K+8!m_m_Q7Sn0OU+aAiVP~*fk7| zn=mpJeVIS>0^5Kr5RViG4x$+cDPm?TJ$+VJ%VWfRiDQE;xG>I@j1T6TK7QKhVT+Lt zveE#ZlzexDXxCg+vX|`m(i8Wro8VA>O-F}k>b=P3BeQ5HK$G9mPprvvDkH(XPD^QH zR-V^~x;>!Qc2*yVyF(-AaeK8p_e7U8(^7cJ!c!*pk=jSGDET9vc*VO-w*H>aQ@T^? z2sDq$DNpBa2MJVSpSDv6dUzRhS+FVpDWcja^rmdx`vWHBtU)b?TwCKdu8^K7eFW#7 z!?pArW>@zTrKA4THSITwS!;DKLyiQwTp}s>a;H9RLgkYUxz*F*z8*v${jzF63HNr757dl(V#_whw&2maFwKGRlP>i#J^%j;YiCh}=+ytvVa~R+mUWv?TN=Ayp2yWd#3P?> zc4^S8ek)2{N1H=!$lM#^b++t)7v2q9*%iT#Fl+toTCKJEv2zCYaqU3-*T$US^HsSJ zUC2|%h88GCGC3vbkgN94O0`s~NMzl~P9*ooD22p($KPK1=Mjk)KO|Q_vy1XX^?i3+ zZwmanfUSPFJgr~#bp9kjy8pkj>IMHlta_b3=gI%cs)zsnU#$An92|Hejr$kYMvJKV z%i0j=8`eQH6hS4!x_Cg*T+B*l7XJ}mfYvl6BBD+n#3ZC>0F zI_as)_J!+NmIlP>5)iN}TB?p4xBmEMNNktR@QM#H?8bpls7MCAfdlu5WypD3mj7~B zIuoOT_o;dnJfxBl`fUg4FrheItE_vI7e6jTFBQ}V)7#vi?J7BVfLobILR_`O-aaDTOaTHRRh z^nGkGr`tu-d48G#Iyf(?Q|V$YvJwPZ{kiMyG0#L_td&ST&($4iH=QK2bAj}^aU!3E zcTrd6Vcal@{4^Hy$5235Is6xEr@yeaX}z81zgasa;FYzf{<5~=U)J9Kf3o(6e^@*I zM;zdPU~Mek7uKFXs$Nq57i*hty|8wux=(>8-Pf;ozkIkRuX}&Cj9QcN=lyW{b!$Mk zks4x6HYlX@rE%O19=c23PJF>ORwmSyKOe z^YsgJ=>8bUdL2^_|L(USH`p&smBOZ|2HOMzOvj=RC-F~ex=(C9GjouyL8~=*_Va7{ z4Q0g_@C{cEyR<*DnFhYye!mm@8gl1##7_XLn<@E9#n}(FYK5yRX6@J$am_ zNGq`*6*9AhM$l4PU1u#^F!7qKghR@H3(+DYV?nCeUxB?0;yb2e6_MLCvrx`OY-^Ey zaULjWjGx@6ZHB@Nn%F*d$?So7ay2RpU6gW>{&p~gLCwuueagXTJ3vyA8xGmjy0B&c zr+np^&ms!4(~_0SFYOnFa{-z_3VwrpIQr;TAIXNa(!fnwRKy;uG}y97EMBK{+dD3k z_6GB1HREQv$9^W}8GNaIPx5rbReV`Z?SDRk6H=|w45O?;9tq2_L46XvphGQ*+$?>V zS9QrdoBVQe*SpN!L;D(hMha73Ao5%i|wjR+&MHxfg%-9!Os_wl$>@z)xKNS*2id%l{uw;}Kw4^j}!q@^&(%IzyfJ zcNiK9rlbD=L2{o`M`M(O(vRxXLHe>M{wk4DKxzI28H`oDRjZoZZJw{h|H9&5?$;0~ z@QtHCbeX{Q2g8z6J4q}PJ!=)paXDt}^ny&hJ2BnAADrws~PCL)XhNWOEVo zX){-K*w~adS{3zXb-b9@0Vt)9YOWQ6Xf-cNMAWGGW!3%}L}A$j9~I}x%D$X}>!pW^ zFy6s6KuuGw3hTTxyw-~F^Wl6Yd!pxMZ(io%TW1K7!!~yzvT2|`=EXmyz)94QaIlH& z_O4Wa#rQP8$2@~j&PzdhVBC`7qIzQmeK2N*7=4&nG!LjxqDlheMH6g1A0IKbN7}sD z_Y{@MRr;9-ysi;FhRT^bELP^?{b3&)D8+_I%>16;)qXoB%`dny3bINS(X~X1oU@ZQ z9uRgL3mL1V#dfLV{Cl@Rl*=^4YSdq!RWnHU50GsLBh#nZrk6uzHBF8}Qbt_E6e(au z5D5r%)SqG~oSNRoPsua5j(*^Yk}VGrbM}Z#JP2iLXccd)fr+2^u*2|6av6!>BG%?; zAzXt8h;?EmK%38mO}dZPD&_k&sDQ0V9rTL%WSHze_E_tE9-kn^;daSz8r8i6S9Iy6raK4EHk@-2-CA8!amS+Q z_wgY=OjXt?%6udjMlh?o@H!zhuC zCiSY~VF$yB?D&Qc2rY(yp63HHuuQXm{b|-B3~?U_wg7&f#!WCp!XXKfWo4l%rv4{y zoKp+g-g~lw^u!-423waqyt(d5u#uHh249f@&f*4ejo zGX2HrBZaiKkNexsOi^-Q?~P!OP&umJ8}tW%;U~>HY5`FB1RBwD!>I<%NxqPmT(+3GVhCAPD9hVY7dpbf4SAHx8aJHg!Rdr{xn}Z3?(aH{|PkfTk>5?-8*Z$<+VId z$7=6A^p=Ds=oFlynAsBDGr9lUrLL{uYM`z$=YE>Hyod-JWhbtAA2YTqz>(%Tm@9?5 z$F(CC$ps^6{21FBh^UHwaTsIe6DjK{;Jn(f-VX!+G(7t?#(dQzAl=Qn6T(JRt(-z1`V&i> z43lX&(+XFj@x`pOVYl6znTC09weHcOgKNJUYw^qETE1RjGyGlde112jwMc&-242UD z5_2WWxk-8V*WnrvM^h!-FPNDO0kx+KsCC@0DPvC?(M1@Um^v;Y)WE=JAChD%bk1N3 zY!A$~O}Abq2XyeRdRU(X7tD}y1$^&6&cOV>AKtRSoMn?d@G*$hu&8w(dfuYIz+%L@ z@>1aiDQt37AQ5S4RB0Zo$J00AvRP|O5`JRCF9u@1#z!5rL>Mt42@tHJEtWf-zleYW zry8%+EAcq9LyBUOm(8Dd{%NZ(R-F^i+@=`Rp;vP1xMrjR>IA+j$_jZ3TlG1a1Ah(( zhs=QK`wy2@16bs)e_M5AU&;$p;Y6+D2zZ1}Do?&t1#$jM zT|-q6d0MN&yd|%+u6mmSUSs>cs$yC5%a@DlSfBW2=tmYUrG`b2tmWZw;zSl<6j1hy zLyJiTRT*byl2C&sElUlbeMMhBaYACo%jmP=)W4P@rPghdH+PcqsK#?>Daa5Y668R^ zS1(&35>#kn#5rWHeh`zyy4Zv{=t^$-Qm0RiE4z7s#2w%(wt4Hr)$h$zB@gX4Lw!g= zcZ%c>%n7cUaKf$-g%v5{o627r(44xp3q!K(KwO5turj6wV{zw_Vd*rSacW2)k0OG; zcMpVOM>g*is~5P`&b9h1D@GKk+DS~(F{{f;4P!Jv1p|*eY{Xh@bBxmwvg3bw7!OT}uP?%mg-CKMWO_ zZ51kQg4o)@NDbsPymeYuo1GQAgPnRvu_!C4HOMLvG-FmPE*h`xqV|_8DAue7*Oixq zfuG*0ApJC|K`B|5RL<3V&|g%g?#6kQN$CKt&VXv_$psT%hD=<+{Nh2RY0bB)J7g@3 z(dLkni2P|hD`lsmlys}Opj~oUE1h@Lgk)Y>1br3-cC?I#!u2l>q*fiqhO$eo$3nEv zzJ3GRYPM*jrg~~Ak`vUZt-=Zs|=Oc@0o?sjycr=e-%*Kxxs>>pa~e{OJP({VrWHdDvQgF>UOKV z5YRr?si&0`tJ1u(ndx_#yXr^Px&hWZbE_qF|IZ@9PTe0yI)r0o--6#@ae`CnS6)ad5KxVUN{{pb|E}Qm-P@GM;ga9 zlb8(DRyT)}H!b&iDq^(c%Q<5r%1CdTPK3m)82?o8I7KHCn5<@C(Eok^)nZz(V(R5L z;A2|uJb{FyaU33qn1|Z|wJr%IfzpQp>rm)05c!W#4$*rv>+f!@_L#XGPEE$5Ke*b3 zBYz2sy18i1d7sDX3v2X~oW@!-retLGcM&i=P-dSe8EJ#YHBhhbqqBQn)ro%j~ZH8$@B%>;E?+k_LD6 zzZ;Q{lgZOtnPn9Ai}j`h zoZBE9yQNGKJ9<36AIV2W8xFi0RDph`6Id$Z46$Wnx2j52)B88~XE&*U(G>wA)IWzd zKnE_~XITQTz1n{pHJ) z8=WCj9oy{kLjp19D$0MtsQJbhjLHKbHsfnfft^K3#ze!Z8A1q(x90n>mIoj`{}rP+ zx%VzO{wIubU+b_mK@B++zA zly1;S%yj>u!o|kZ_4W6oZwy(qo@;+@B5IsQJ4&B^7Ph8t-HOdl5@R#Y`n3iyG-MCE ztP_S485eD!0Kw~BxVzVENzW990>@YM}2VKH9=7-d9tUD$KDxto(*sf z_7y%&_LyD239~3lZU~>?#}9wf*L`}b@jRXM4164968d^?--b6dMPE~VB<=BG!$#St92jX$PawHs+Adwb@cuxR+V zNW#CX!k2%QM2sR&p2apEVm@m1;MTEC_04hE?4#Y`z%He~hiDjWiv11*3cE#iY03qI?1nGxcpMc`3hEI$iSQZL3@zH|3p;jV$#K-tU zr5{KF+!Bf3ZA*bb$zJo>I9P6K)i#*aR^*Xp0PzZa(4l{Ujt{9c4x&jE$yZKH34H5d zOX`tzJ;V`bs0ni@iS{8pCfef$Lt=0!pn)z_9VxgeBvIY{lF@8PgIgIW%qZ_a|fW;yY2^Sb)|& zx4!j_b2Eh~_R=h=DB8v`G`Qv-p}uFXDp_Q;chG{DA_Sds=N(M9Iu>o3FakKV=>x#m zd8lmHg>`Uu2z8F(#9N)8YOoUa_f(ZK2D~j! zBYcg9@&p`3v5%%N5f0*|<%zex4e~GVho1roa*r~;M8i&{0tx89yw~gsPeyYG<5=Q3 zulX5OBCq*patEdE%J?#@F218XTOSqGe||Fy1l0l^Z8$W`<#kHr5m;wjgzzg?5uAs+ zqi%08m|E;@y2655#sQ0rlq*Z@!6EX&Y~{}Q1mzaS_sSGH68F>MAf(nyI8X;`=)F~bZ6h)N?P9F`@|BIDR&uky0q z5GltX9G;M47v2~hB{R?SLOj7muo`EGq_v2#)iQDwKrKk`%ZrWtKD;P$;Sk_AsC2le zA~mC`PZU@Z$cVGd9))Qh8>O>C@8*U>$s1xzb_K5LfR|Rq(F+F~(LydgG2xa&;*x=S z#0{=pYCrO^_5u24i8kt-job3(FBeIbk&^i9qBZ~p{(i+}s7CM5Qz^xq%m6{|AOK>d zM;yW||HXI;Je}e;eG_RaEePQ^aQLO}kjasbjI1rzPN8zSTHR)t4Xeqb1qA}pyC%vM zgc*roaZ>5pI4npZ)^8YI2A#qwx*#P$aGy|HkCJVD6rCsnxHtqM10dQgGL%nDWt>d> zPKQOX?9CVq#3q3kukr^;vZ=%_ZZ`Alg27{m)+eT#fJs3`IZj4Xwovm}7g4%eo4Q|g zE2sFUqghR);qhEVM@4i^5a`yVK>XW9&gSYf00j+_x1QnN8I4YT02Aq(R7j4viS)^* zPe_FYDlScMdJb$Pf|%SEKqNsXd1gI%3Q*|nv_yb>Byn}9Xd+%WIb(tLzOXaV6wDT0 zB}X$HQ=1Ex0!64B1~~O)KSJeG8ptPMU@G>PZ&Ag82JhanX!79|mTJ5d1vFAK;g5-_ zq~Pd?9c*}1bx zUd)U~3@aF!rlTor>}BpC1fF*8llSixC%&I8mhlnFOFyqJuc|70XNnfiguap0ftt8q zsZw@a@M#5LW&nzxf6W2;@41r&!w*v_`*^u^S-{7P0F#@p&^lI*e%`JLS0Mf&cqFt2 zL2j6Gz}{RvGyOGyCtw>NxD&?a7u;cm>dPcTQC{nd19}xeGa0fL43rE$uMkeA!%Ld! zhs{t~rq%+3i%~;wxoaMdkG(3eR!jl^pkI3|pps779k!x|WFENYZy;id>nh;{7%7s# zXba!W5=EIwBMCK?4BOYxni4Ad5}f-JsaaQRO3groHM^o_lk5n|fphw%q-JvfSBlOZ zR$v}j{3Uqx&)<^b3!va?8{-l{3Q@|pW9NRFhcO(qaaUgVj!v4D{w^6g%HfU&*T~+W zhbDmh)-elQ^HLl*+RNJG0m;$(F~ER{l;I? zN9;eDY&5>iJo~pvVRZ%Fl6R<;W=tctYAOL1I#S^kq9~BXy0_A^X)WPp^IeF~oOuQ3 z{+#~tCNaZ#XRlz;T|-8$qgSt_EWox}bm8XF~oG!n(qdsEg}{=m`&A ztGFv)?`9}PJur~1et7=Ai z70mmrOQn^3WhrA}*4)omQ6)()OZ6Jm0=Odh!8`ozyhLcK&*w*rsqq_$Pc3W|Af1H?I_awAK8opdrvXlmi5QJ} z>tD7ck5rG2MU?}CZdl>7XIIS{91Gpk;fO5p|L6{g8!L9QNL#72GX{2t)UT#5rKIUD zLD5+6M0G`^-O9wkOiBsy%?cFWlP}7Hbs1Jv{|3V(+LDM6W0PYN^u8PCkYv>;qybDL z7liVfOc{RJu{-@^1`h4L=C8`5&jSw(=?hD0RmQ}T-9En~XXMhm_$GplV?c*qN$w`* zM4;ZO?IZ{T80PM_Wl{NLnbI$jzMtH0UcmtA-~H6sN`FOV?hGEyXlUh!^qV)vbu#Jb zbHeeg3~e`vgGaVSb@YjL@&nd}<+CU(J`xuhiUjE{J2oh@w1Yr#HH<`-lxt zEo+SN^TLn6cx{Ome_JB^MbgeY_Frh@H6d>dHQ;rk#}t5q){?I&Qg5bwse#r>kj8-V zlH}MgtNc$x6z@}&OTLRj?iG>nLm~EqnKZ{*X(Mf3yN~>;a7p6BZ%b^^kjxzUQ&7O9 zsX^Noe31$2M**nKOL zSnM@%{OAOT@#5w8TSHtnKx6+Nz^eVe5}PwqHtf!KWhm(cj@^({F9O|y>4viawD?5PzUbh?;L3_mS5|RWiiRj>MIjH|`1<$L zheyxcce|S*x2u5-TaH&6Sr2t9y5=yR+oKPss+9*>HoESHndmaxt((dn7*$_NZ!I6j ziu+d_`bxAYPu{QOu_~ByXmv0n59=mip3wL8s3%iWM&LJ8JGalNa_Q;j_M|=yOB<%~ zg8bI%81tM7**(0bszeH8H~oQKZfM;;4|<_Y4gITWD_`B7rXkGur;=zU(5Ny3K<8-IJ= zVcaCS@mt!T=Kbykl-UZAr~u=$e=oxLGEy!#k-ItN&8@BGeI0Qo+k_SY`@0D-BJdY9 zn$5Q@lGZa#__s3Y7VsdSE<-sqd2vg#p?L`zrvrY1a1Y*vpW+iWx)Ht5o-3ifoA+V8 zX;8w}E7S_066;mtOin-l#sJ-6B#%}o`>jmI4%mUT2x{VVzLED=d9otr;c!@hB zxaR8Fp8C~5quzw}K+Xi#XB``E&{%FZz=55ydOw&=#%0p{18wEt7XKEmo(XIo^2L`( zGy4GSw#|izAR#84wSi`3#@2CwpEzS{+~e|=zLVMelex~PWYy31%|C7^G*$;l1{aHM zRuK?o=Orsvh<1yAoBftM@r04Pu(PW~3P#45QgYiY99G71Rn_UOV#n(K=?8P<=faKW z$A5BjUoBOK9X^Lmraj1)anI^Yv@WUCNKJMolbJaI`}HcZfkAmXaSE%&xwm;IgjQqwF4wpqg}~ zJd8AjQy8OG6UPYxnp7H2nN%8at)#_lgAsAD9ERu*3=U21Q-$+EYBlOe_I=i8QUaJo zChx`sCHu9WMZ1N@Bj4L>KkG9-QT|LC3bBR{hME1{Fj5~=?zSTzKIe-yjxy;1I(ny! zmk&B~4gCpzo7_*Fz88;mR76S3F_qogIsL#HmZ*T{WnO?pm?CGWJs62A9!rH8q9jf@ zII>gc&SnlJX`e|GVjw(t(w1Q&8ZF}Nq{}%BciPhBl}V)(Q%XH|DLe%};K$%4uC1M9 z@{jDDT_|YmYUC{F^?XA(dJW>$*T!g5B>B!?8NGsux55wB1HF4U?|dGIz^fFdSW(uy zGp(&3_IC_+f$N{08)U+j0rAyzE70ssM;u~pj%hP~k|+0A6eaXWQ<%L5G!9xE4o6SW z?7#l0+lgq7&f^U{yljv!ML*OZ5+S0ckny6i|L|veUi_J4E;jI9*3svV92y=%yKN$q zdOS!P!8mN3P+~hrDZQM_q$S_%jMFKVqouArvc2V>FTdnJy#)I&d9!b`oE2q`$t%Y+ z$D^DTaoriU>y)37h*u~jR*Q*tVNOiqr_TlQOk=0(dr;9xNRu{V}~!XzcDGNz7M1K7wYVrPK^RE00>+J}^e_R!wY z@CKuaSia9^`?IGOyY57B1I?SqBs?rOzSas&v0_2nKb%GLK^qcf*#AR&$>0zh8a-%# z5`K~k{fK*jV8a%juAN*h>6TrRW7tt%*n9%9qn;KRr$lch0A#TYOurZ};>|@gzg}BX zk@3CcpfjuGz~|!#p6raGpn5MCne_5`6fMXyud6Y6e#hk7ew}=s;$3<7(o}IAqtyX7 z#v37Y)}ORkI(#rWRAT$b4?_fl>Xs$$2lS^^5(lxK4LM5Xwf0VW6KI z95-?l-TV?SmJ;OwKae-%C%O<3G4cGhYvjuyg@cEq)xqS9jgu(X_pVzUPEN~a$_?5G z8hA!3x@8&YEVF$)udm%0QWxKJ&*B`QYk^ZVJRC0mQ$ri9qZVBz^R_EG#HjKuO=z=d zv33mj0N{2F$GgE_yi>h+Pb7yXGv62dmJqelwVNu2mli;eh^KQ3wvMKF=XH(1PyEeW zd(fNVhOCNh1EalDvM#?`D-7;Ee=Nq z=u^!PTyK>yiwVS+Oo_)b&!0${rP@Gt>wI(}tR3sr+l~6{@b;c3zI4mhM0?9=zJi2B#Jn;!tHZ{NRtYfyCtM(+5wi3-4zQx+ijr{`PD@ z*2qazu{HW^CEUl1FoRXs?1G^q8m9DSWVI?M^L$8EH&V zlzlJ^DlKYY8yJ5GbKn1_9W;acK+P`=Ba9xP(iZc29(SNg0CD><+?f0)a}_3bYwjl_ajr+qYbMW z(F9}07i^|%O41`GofICFu{LIWmx6z}%sXfPrB^S7dVHaGZ-FZa8X{B%cDV@93lAYc z0HXm%BAZs&(kwjym%)IL5S~hww`GEFzb6n25gz#0Ag5zjbP533`48i6Kp_o`)G|pB-fFM9T4iMqcr%(@TJZjwt zSzu4Q`HXkK7{1?(aZDv%YXE5?GNuMJ)@?+Mu{mbulTsxRV~8=2W6V?^is_lk{q`BN zfUkDb7w>>EV!s)~MbQCS0;QG!Dhm!yR0NHx%&F)D)5I8J%wrv$*oF0ZkM>Mm2=vQGBXhGf2`Bd0+Pv%y;C-+zSO71~wa{9ds5c9(-M&w!r|g4CAGe<( z{4z6d_gst}Fh(AEicm4bxJytlkYq*l;IavzO+lBuR*14OrZHwS#=O%v%H;8TyZyD0 zbNJfsF&H~wj5>10L>s&cigcg_NN+9ahW<#B3$kpIb&D&@8)F({9$9ZaiI?GQa&exv z&X_rTZTHlRZW&{xR_@5{nB=rz!DP~{XCOn?;CR#|r(7iS$z=ZfmQ&IbH^MZ+d>e$> zNi;?uH(>-8u7h)=pIWRz;J1&Mfn0#WcbkBw^ln9gER4G}UqBlpflELlp0g zHVG_BU45ktA(M7dG9#i)T8r3>n1+}`MNHSB7~?F8tKxGi0(M5=O5fLRXB2#yf1(@N08aMiW$GZ?ZWN`8RTVYJ+;TUI*e)Sy|#zo!NJ)x%u zlLf(L)F6Bg%(4_YV=Zsp2y>W(*-4#}J#NDI#6wDjgA-1Xr-T^-4-v9gz6cX?j&1c_ zW6Y+E`S{M9Uk`6B|3>PRCY{$QIfGgqapJm2g;|q`YGfB=k&)b_>>+B)SW+@3&RgQT zG3J07(|I(;8qSZIF{mB7U;-GPB1jV>Sc@DOx|oYlOflUU(-?EWjOn~m$y)2gkteRR zL|d2#B?CQJtOs6|8~{DKEOVkJYKwduV-A)voyTLGs2CI6wV}Z$MIIH)EKiNW3F$RABT5#a{aB?G2Mq_ zP>SPNfH%&k{mFD;SNQvQjLmhcUJ^po8Dt0!oYwT9p5z?3=ON^lT56m*T+Uo|AChtU zNNkz)>1z{FXPz@?$H`gZk>r#uJs(*!PSJB^85(06V-A=x-7k@mB(9@i%%C5}ew``f zL&TT@DS?GT4^|X7ClIodXjM=pOWypY#+XB8Oy@Bfr)$yDQKzr1Dn=HCP*3ayiM(!8 zl^A%JS&oi5=UHP+W6Ys4W(P4Di~P75qfqfEbcXD_uA4h}QbvvYYGoA9!DpWvV;W-) zlrbN6akSErFy_JBQcl@8?K3!w2-1{D;x!UvGEw@HypxSFjWHWCCiX9Guia_<(BC>^ z=J2&m#_XVE$sWluwCiKOEIS=CiAWg|iBz^KHzf$XSk0W4QDKYuHpUzgv5izqLTKdEyHV!Ibg>8b;)149bNpg z_0*E&g1M&|!z1eG6N2y}f%G)+f|dqEHZCQlif8;;j1m9g)KZX^6~PL4dJ>QcBUmp2 z1nbCCGFk|gc4Ws4qBEh4Z*ShODSYtM=1E1m!=ynLN2;wS=wdcD=4>rrWc&k+;XN)~ zPq9Un)k|9TxOMarxiNpN1LBC*5bCfXFmC}PKRpQ&u^~uKe#(RFC;0>)L5lb~q>Qfz z`TX)d(^nfH<*Rw{etfeFq~LKQ#mg9K?GPE{WN}Md?Q&;5S>8z%mA&=SHl#G9tkwPL z)v35vlc4g}kupcCZ6al`3#5o6w^E8Ba-e}Akb^YVf=5q}m{YP@g%VlwS{hQ;>%M>H zZ{NKiT^g}fPxMw$()FJp9}b>k@Ix0C+qg`ZxH^HST_hr0^za-6=s z@4fFohCHSLG`cwX%f({QuQvDiYBJ6BIp}YB?%HpESp3rAWq*+0)@GWukdP9k;cVem zXMS?FdPBpcX3bPEF^fv;z)DmFBMR#kw=4xC6<@xy$(iS~Af2}grHITI?WtXPNZu>W zv{g~@oJ-QRmMN`yKYiJ(=E*0?qGMijo`lZixVaoqQpd<*=*`}6k%F+I6s0^9-m@Ys zW`|63KNnZujysr?)<(@h2WAp;20ajIDd!q<_0|FC_Wt*=$(- z_piUc8jnuLet7bdhQ{RAU*|^Ji#Y9n$aFpAUw?fueElIVp`(7%n!)SGu{KV;8`|I9 zXt~@({o&=^IQuRNmdKL`G-((iGxeC&88ep5cub5hw8RR1{{3anrS6;d6oeILln@EPUbRXwZ)z*MH;p_`)$Ket;j4W-IwU zdjT(AND20PfiEPNFJG7!>nEIl^`~biKU5O-FHRr5sa3B)Jp8 z{N?1QG-FL4GMw(xIbLwhqyy#Z68^x+V$q=hmqG^NN$Fzkp#Xl6#|s}f9HpzlgI3zp z$(~uZY3af1ggL|F+R5N446i^q_;gZVyqwMWg5Tl?lP~=JZT_3;jX!!XYq)z)-Qv&l zNqxYR`h$h)Z3b*XlFBy?dl((`R&j@#*$o|ML3hAO5yz72PB9zaIO9JG=_1^!#wm z!^^j|o!`!VO#R{NXEodWKyCBgv1J1jGurwGS7|u^Y=yCo$iJr%(bKeqo zcXo0;CL3b>d`D%`OqpHgYrpu@HJlgq%xiuaEz{9?Ug2RH4Sjz$TK@j?$%}vf{O5oC z^p~H1S-cGbWIi3&+a1tMU57T;!pg^9^Ld0!KGHxKEH>iy+O z9QQBpje(!?<-o^$;!o~I@5$`zPCh-`AC}*pFY4g=JPuc`-{0ly{9;na@vCuv=*J&_ zuAlbm{w}{;c-L=p|N8ghsQJ{HuYrRCZkH5sX9`U3K6<#gj*VV%HCcfA+D^Z^yqiAQ z{14Z@@%aw!`QY~Lyo38{bRo9x;2K6WeA>Zfj2Y#afRc&_8qtZE931cx3prJSi%^~w zGvht?AB~wwlUdYS0oKKeGT8#blNlOh4w{-r6}GDti|T50!_EqKYl=iPVva78q3jDy z&Q?co7#+lHL&{`71dC73%ZjF6-9v6So_bBHldesWsH+vErPV~7L)Ks!kQ<^nHQdof z%`gnl?E9PX`wzRw^`G-bgzn4AxrrLB23HSuk(LJt&PZT6`XW=dPKHK=MuZ25FdE`@ zxs~c-y!ANx9Bj52M<2Z01yuNPLxm+SbS?;JgaPTZ0dFw_=Ya?3gp9dCr9tIEsHE$g zcURMC+Wr!vIbLlODsOfH6+CXJATp5%AP|&FAeox2N+fedIj+1UgC)BLl?Igupb{q2 z_ZP!kd40NlsC?noHlZ^3cA@e#I9kTPW&B&le}6On7+E$k*7%?%#nU7Uo+(|Ael0Zd z(LmB-yBU9W_Y2niasO-mg!89d{MBH(SGj(}gfs~`s8Sa^W6am5_d@n86|8=?k<@P+_Tz|96Tekn;8?Q#YlA9Zo$X(SOUw4RZ2v~i z?M`xg;?)+1(f zQ}GrfX2YH2_T+Ix#b$0?-D#-^3?K_VopUylo312xsIc(dpwgi708|{mDtd6^^K|P_ znd8+qp|X?Qo;q%*#HhV7#R79NfmAYs69&N(ZITqpdfRe)4Jr>o<$|&6>A5_Yw_AtG z9Iv(sm7V1F^pUSZaxz-YEg2H!L-K>=cmIDIIsN>j*MXj~8#~fP`nqv|c2p;4IVdCIRCKc7v7Azt$VH;E$R1OI$ zJ6Ww_jyngWvXdga1T0xHR$z!QlPv@cQgqflAkL z6+v9lN1j-=C2K}N0cs2mk}*jl(H^ujOy!cJN~|T88&VDgDLbkEvB$muPVtaPqY|tC zBS=HuumV`T;Kc_fvu}1vgUSO?xw#mJ3x9roe)Emg|6Fz*QDMeddE|ThVJR}Q;=mLm zNgPhmg9!)LV-g`L?t^Z2N<+$FAm!tae;=|xzxZSNlTrWr@!gNV{BL=)f|OyNj{9+r zDe2ROG{1)}l1YMul4^tVx3bT5!|nvd#|$#oGw>v%k)@;L-ZQd$!XxKzt>ee<+#QH> zX>ITsh>2ubWD{uAqXq9Hdhb%UTpz-DKnuImeCeX+;L3+#IU7cGezm6jNruE@JqgG- z12Sb^afN`=8WEhRQ_lwHkkD_#dMM56K_p!CkkN0qa>vDd+|v zL?{Tlp6)Dqk`An0iR;UtMTYTQ1FHA1;3sYafK9TuRA4$ zvrm)4#Nvwa0?>L*6AsT1f>gDL-+Q!$+r?nx5-GM|K``M|$f!XmL8Q>k5;HVSC_#`X zVU@H_94slEeGVz&&8<2e&_K9cV?l&$$>kKFov!F-g_Pzw6epv=AZ2#yNm58l9uMy! z;u-^j`W@;2)hi6E4I$X(C!FO90`i5?gC#F%X%{2Kz>$lT0BJN-oE)Kfar)-g%||kZ zzodV50u3V_XPPr3pN57LLI&q0gi@%3Dn2Yn@@bt$RtO|1KjwDe*Fz&~a(1$bU|baS z&^}xD9`QA0Vl+*LeKKyrRDIiq#X-Wu%6r ziJPh9y>aw!^iLZWf>`!skTgk{p4=P?T9G3Qwi*x$;_;XVr-K!x54%yi;;5U_ z_f+YhJ7+(Y&JDQ{f~*6zqI6X~g*oT3Dg7a(^A)Arj+8DWHl^>Y((gNGFO@Fne?>OE zZgPG?&Sx)|<(z-&NX|;xCg**X^L^*+rJRx6b|dQi-SqsFo>yG%JnBf##>l4Uebw`Q z=j^4P$)_fJ+q$Oar_T;vQ1e8_*Bu7XjMnODHES1A)E22D_-soC4c0}3Bt45Mx)?Kd ztLB(k3dzt=aJE)NNxFj+0x+ADFG1R%_`yZpzjV=aG<|k+eQ|d4{^LlmsaoaE3ma=z zi-)=pgWyQUJp>VbmVsNF_$DT|wLPUa)^tt~4LA>m<^`G%mQI!l8LR>2YlJ-+Kz=l$ zAG}-on-y5d z4#RN`7JChg`!3o~3qkj|Q{>ExRai*TbJ$y5@#lDt{+mCev4P^*=kP9pBK@tyKwksJ zUW4Mki}n%}sC&9*>sD9!B6B@Q7?H98;j4kL5?e_94kLvP2zw2L`!3o~AaL>)>asq$ zc12%ZyJv7+Nr0jEAU0NfEh~mEZ(*JlZ$|H+vp6JYPU9x^Ln#WZM|fosEl8&dv7!V> zx`b4i4kkXf`d4hBen=FbnM;5n*Sv<3;4RTATahj2mTQ&{G7kBvi=M*@QO+;>fyvv^ zn%qLkhH00n2L%TyjRPx?9#b0=5`8oB4RVFT^yn_DtFf`}ovC#|UO|Auz%11}I`AGm zXazJSnYhFRYWq@aB{iS`e}s#Chi{hHAWvU)7Opgn4f`IhH2cejS#6o;oq9SXZP| za~4Np)AUcw#>Skj8K_kqhjW`q^9 zH5ABXllyb!z7jmR_+xi*#U}T?k1Ou6+!^n2;d*La>_FBUEqX~K!E;IQZsj1m;Xk?y zBWg>defx(xY;bVH?<4`ndUj42+DzHibf4RdEri2p$}~b#7~{GmnTGMJ4-FB zskh*UI-JwBb&&(21HBVbw}T}*g2&2%b;Hx{B8&|l`@5;4*37hr4{*xwx&#r|Rd>uShas_hyEy1~Ht>alQt?JkDcFtEQnHM)Ja23(KVqRSP3 zL71MX3mjK3=vj85p7+$q(G59Pf)E#_yKrP9$NugKsrHu~?U>5nPl5jj=U5XJIFbec DzXCnw literal 0 HcmV?d00001 diff --git a/x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/mappings.json b/x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/mappings.json new file mode 100644 index 0000000000000..13a16ee4e646d --- /dev/null +++ b/x-pack/test/functional/es_archives/endpoint/resolver_tree/api_feature/mappings.json @@ -0,0 +1,2906 @@ +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "events-endpoint-1", + "mappings": { + "_meta": { + "version": "1.5.0-dev" + }, + "date_detection": false, + "dynamic": "false", + "dynamic_templates": [ + { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + } + ], + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "destination": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "compile_time": { + "type": "date" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "malware_classification": { + "properties": { + "features": { + "properties": { + "data": { + "properties": { + "buffer": { + "ignore_above": 1024, + "type": "keyword" + }, + "decompressed_size": { + "type": "integer" + }, + "encoding": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "score": { + "type": "double" + }, + "threshold": { + "type": "double" + }, + "upx_packed": { + "type": "boolean" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mapped_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "mapped_size": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "dns": { + "properties": { + "question": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "subdomain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "resolved_ip": { + "type": "ip" + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "endpoint": { + "properties": { + "artifact": { + "properties": { + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "type": "object" + }, + "group": { + "type": "object" + }, + "policy": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "type": "object" + }, + "user": { + "type": "object" + } + } + }, + "event": { + "properties": { + "action": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "sequence": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "ignore_above": 1024, + "type": "keyword" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "ignore_above": 1024, + "type": "keyword" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "drive_letter": { + "ignore_above": 1, + "type": "keyword" + }, + "entry_modified": { + "type": "double" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "macro": { + "properties": { + "code_page": { + "type": "long" + }, + "collection": { + "properties": { + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "errors": { + "properties": { + "count": { + "type": "long" + }, + "error_type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "file_extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "project_file": { + "properties": { + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "stream": { + "properties": { + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "raw_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "raw_code_size": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + } + } + }, + "malware_classification": { + "properties": { + "features": { + "properties": { + "data": { + "properties": { + "buffer": { + "ignore_above": 1024, + "type": "keyword" + }, + "decompressed_size": { + "type": "integer" + }, + "encoding": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "score": { + "type": "double" + }, + "threshold": { + "type": "double" + }, + "upx_packed": { + "type": "boolean" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "temp_file_path": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "group": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "containerized": { + "type": "boolean" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "geo": { + "properties": { + "city_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "build": { + "ignore_above": 1024, + "type": "keyword" + }, + "codename": { + "ignore_above": 1024, + "type": "keyword" + }, + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "variant": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "bytes": { + "type": "long" + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "fields": { + "text": { + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "bytes": { + "type": "long" + }, + "status_code": { + "type": "long" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "text" + }, + "network": { + "properties": { + "bytes": { + "type": "long" + }, + "community_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "direction": { + "ignore_above": 1024, + "type": "keyword" + }, + "iana_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "packets": { + "type": "long" + }, + "protocol": { + "ignore_above": 1024, + "type": "keyword" + }, + "transport": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "package": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_percent": { + "type": "double" + }, + "cwd": { + "ignore_above": 1024, + "type": "keyword" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "env_variables": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "handles": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "malware_classification": { + "properties": { + "features": { + "properties": { + "data": { + "properties": { + "buffer": { + "ignore_above": 1024, + "type": "keyword" + }, + "decompressed_size": { + "type": "integer" + }, + "encoding": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "score": { + "type": "double" + }, + "threshold": { + "type": "double" + }, + "upx_packed": { + "type": "boolean" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "memory_percent": { + "type": "double" + }, + "memory_region": { + "properties": { + "allocation_base": { + "ignore_above": 1024, + "type": "keyword" + }, + "allocation_protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram": { + "properties": { + "histogram_array": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram_flavor": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram_resolution": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "length": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "module_path": { + "ignore_above": 1024, + "type": "keyword" + }, + "permission": { + "ignore_above": 1024, + "type": "keyword" + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_base": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_size": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_tag": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "unbacked_on_disk": { + "type": "boolean" + } + }, + "type": "nested" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "num_threads": { + "type": "long" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "entrypoint": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "start_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "start_address_module": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "phys_memory_bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "services": { + "ignore_above": 1024, + "type": "keyword" + }, + "session_id": { + "type": "long" + }, + "short_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "call_stack": { + "properties": { + "instruction_pointer": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_section": { + "properties": { + "memory_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_size": { + "ignore_above": 1024, + "type": "keyword" + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "module_path": { + "ignore_above": 1024, + "type": "keyword" + }, + "rva": { + "ignore_above": 1024, + "type": "keyword" + }, + "symbol_info": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "entrypoint": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "start_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "start_address_module": { + "ignore_above": 1024, + "type": "keyword" + }, + "token": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "impersonation_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "integrity_level": { + "type": "long" + }, + "integrity_level_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "is_appcontainer": { + "type": "boolean" + }, + "privileges": { + "properties": { + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "uptime": { + "type": "long" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "token": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "elevation": { + "type": "boolean" + }, + "elevation_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "impersonation_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "integrity_level": { + "type": "long" + }, + "integrity_level_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "is_appcontainer": { + "type": "boolean" + }, + "privileges": { + "properties": { + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty_device": { + "properties": { + "major_number": { + "type": "integer" + }, + "minor_number": { + "type": "integer" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + }, + "virt_memory_bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "strings": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hive": { + "ignore_above": 1024, + "type": "keyword" + }, + "key": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "value": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "rule": { + "properties": { + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + }, + "ruleset": { + "ignore_above": 1024, + "type": "keyword" + }, + "uuid": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "source": { + "properties": { + "address": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "type": "long" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "top_level_domain": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "stream": { + "properties": { + "dataset": { + "type": "constant_keyword" + }, + "namespace": { + "type": "constant_keyword" + }, + "type": { + "type": "constant_keyword" + } + } + }, + "target": { + "properties": { + "dll": { + "properties": { + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "compile_time": { + "type": "date" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "malware_classification": { + "properties": { + "features": { + "properties": { + "data": { + "properties": { + "buffer": { + "ignore_above": 1024, + "type": "keyword" + }, + "decompressed_size": { + "type": "integer" + }, + "encoding": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "score": { + "type": "double" + }, + "threshold": { + "type": "double" + }, + "upx_packed": { + "type": "boolean" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "mapped_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "mapped_size": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "cpu_percent": { + "type": "double" + }, + "cwd": { + "ignore_above": 1024, + "type": "keyword" + }, + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "env_variables": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "handles": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "malware_classification": { + "properties": { + "features": { + "properties": { + "data": { + "properties": { + "buffer": { + "ignore_above": 1024, + "type": "keyword" + }, + "decompressed_size": { + "type": "integer" + }, + "encoding": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "identifier": { + "ignore_above": 1024, + "type": "keyword" + }, + "score": { + "type": "double" + }, + "threshold": { + "type": "double" + }, + "upx_packed": { + "type": "boolean" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "memory_percent": { + "type": "double" + }, + "memory_region": { + "properties": { + "allocation_base": { + "ignore_above": 1024, + "type": "keyword" + }, + "allocation_protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram": { + "properties": { + "histogram_array": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram_flavor": { + "ignore_above": 1024, + "type": "keyword" + }, + "histogram_resolution": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "length": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "module_path": { + "ignore_above": 1024, + "type": "keyword" + }, + "permission": { + "ignore_above": 1024, + "type": "keyword" + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_base": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_size": { + "ignore_above": 1024, + "type": "keyword" + }, + "region_tag": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "unbacked_on_disk": { + "type": "boolean" + } + }, + "type": "nested" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "num_threads": { + "type": "long" + }, + "parent": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "ignore_above": 1024, + "type": "keyword" + }, + "subject_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "entity_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "executable": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha1": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha256": { + "ignore_above": 1024, + "type": "keyword" + }, + "sha512": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "entrypoint": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "start_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "start_address_module": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pe": { + "properties": { + "company": { + "ignore_above": 1024, + "type": "keyword" + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "file_version": { + "ignore_above": 1024, + "type": "keyword" + }, + "original_file_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "product": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "pgid": { + "type": "long" + }, + "phys_memory_bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "services": { + "ignore_above": 1024, + "type": "keyword" + }, + "session_id": { + "type": "long" + }, + "short_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "call_stack": { + "properties": { + "instruction_pointer": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_section": { + "properties": { + "memory_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "memory_size": { + "ignore_above": 1024, + "type": "keyword" + }, + "protection": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "module_path": { + "ignore_above": 1024, + "type": "keyword" + }, + "rva": { + "ignore_above": 1024, + "type": "keyword" + }, + "symbol_info": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "entrypoint": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "type": "long" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "service": { + "ignore_above": 1024, + "type": "keyword" + }, + "start": { + "type": "date" + }, + "start_address": { + "ignore_above": 1024, + "type": "keyword" + }, + "start_address_module": { + "ignore_above": 1024, + "type": "keyword" + }, + "token": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "impersonation_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "integrity_level": { + "type": "long" + }, + "integrity_level_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "is_appcontainer": { + "type": "boolean" + }, + "privileges": { + "properties": { + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "uptime": { + "type": "long" + } + } + }, + "title": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "token": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "elevation": { + "type": "boolean" + }, + "elevation_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "impersonation_level": { + "ignore_above": 1024, + "type": "keyword" + }, + "integrity_level": { + "type": "long" + }, + "integrity_level_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "is_appcontainer": { + "type": "boolean" + }, + "privileges": { + "properties": { + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + }, + "type": "nested" + }, + "sid": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "tty_device": { + "properties": { + "major_number": { + "type": "integer" + }, + "minor_number": { + "type": "integer" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "uptime": { + "type": "long" + }, + "user": { + "ignore_above": 1024, + "type": "keyword" + }, + "virt_memory_bytes": { + "ignore_above": 1024, + "type": "keyword" + }, + "working_directory": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "threat": { + "properties": { + "framework": { + "ignore_above": 1024, + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "reference": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "user": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "email": { + "ignore_above": 1024, + "type": "keyword" + }, + "full_name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "properties": { + "domain": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "hash": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "codec": "best_compression", + "lifecycle": { + "name": "events-default" + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1", + "prefer_v2_templates": "true", + "query": { + "default_field": [ + "message" + ] + }, + "refresh_interval": "5s" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "metrics-endpoint-default-1", + "mappings": { + "_meta": { + "version": "1.5.0-dev" + }, + "date_detection": false, + "dynamic_templates": [ + { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + } + ], + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "elastic": { + "properties": { + "agent": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "endpoint": { + "properties": { + "policy": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "event": { + "properties": { + "created": { + "type": "date" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "containerized": { + "type": "boolean" + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "build": { + "ignore_above": 1024, + "type": "keyword" + }, + "codename": { + "ignore_above": 1024, + "type": "keyword" + }, + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "fields": { + "text": { + "norms": false, + "type": "text" + } + }, + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "variant": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "stream": { + "properties": { + "dataset": { + "type": "constant_keyword" + }, + "namespace": { + "type": "constant_keyword" + }, + "type": { + "type": "constant_keyword" + } + } + } + } + }, + "settings": { + "index": { + "codec": "best_compression", + "lifecycle": { + "name": "metrics-default" + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1", + "prefer_v2_templates": "true", + "query": { + "default_field": [ + "message" + ] + }, + "refresh_interval": "5s" + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/functional_endpoint/apps/endpoint/index.ts b/x-pack/test/functional_endpoint/apps/endpoint/index.ts index 3e70a1cc67670..05fed43d1272b 100644 --- a/x-pack/test/functional_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/functional_endpoint/apps/endpoint/index.ts @@ -15,5 +15,6 @@ export default function({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./host_list')); loadTestFile(require.resolve('./policy_list')); loadTestFile(require.resolve('./alerts')); + loadTestFile(require.resolve('./resolver')); }); } diff --git a/x-pack/test/functional_endpoint/apps/endpoint/resolver.ts b/x-pack/test/functional_endpoint/apps/endpoint/resolver.ts new file mode 100644 index 0000000000000..417073865df7b --- /dev/null +++ b/x-pack/test/functional_endpoint/apps/endpoint/resolver.ts @@ -0,0 +1,259 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function({ getPageObjects, getService }: FtrProviderContext) { + const pageObjects = getPageObjects(['common', 'timePicker', 'endpointAlerts']); + const testSubjects = getService('testSubjects'); + const esArchiver = getService('esArchiver'); + const retry = getService('retry'); + const browser = getService('browser'); + + describe('Endpoint Alert Resolver', function() { + this.tags(['ciGroup7']); + before(async () => { + const fromTime = 'Sep 22, 2019 @ 20:31:44.000'; + const toTime = 'Now'; + await esArchiver.load('endpoint/resolver_tree/api_feature'); + await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/alerts'); + await testSubjects.existOrFail('superDatePickerShowDatesButton', { timeout: 20000 }); + await pageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + await testSubjects.existOrFail('alertListPage'); + await testSubjects.click('alertTypeCellLink'); + await testSubjects.existOrFail('alertDetailFlyout'); + await testSubjects.click('overviewResolverTab'); + await testSubjects.existOrFail('resolverEmbeddable', { timeout: 20000 }); + await browser.setWindowSize(2400, 1800); + }); + + it('resolver column Process Name exits', async () => { + await testSubjects.existOrFail('tableHeaderCell_name_0'); + }); + + it('resolver column Timestamp exits', async () => { + await testSubjects.existOrFail('tableHeaderCell_timestamp_1'); + }); + + it('resolver Table and Node data same length', async () => { + let count = 1; + const tableData = await pageObjects.endpointAlerts.getEndpointAlertResolverTableData( + 'resolverEmbeddable', + 'tr' + ); + await retry.try(async function() { + await testSubjects.click('zoom-out'); + const Nodes = await testSubjects.findAll('resolverNode'); + expect(tableData.length - 1).to.eql(Nodes.length); + count++; + }); + for (let i = 0; i < count; i++) { + await testSubjects.click('zoom-in'); + } + }); + + it('compare resolver Nodes and Table data', async () => { + const $: string[] = []; + const tableData = await pageObjects.endpointAlerts.getEndpointAlertResolverTableData( + 'resolverEmbeddable', + 'tr' + ); + await testSubjects.click('zoom-out'); + const Nodes = await testSubjects.findAll('euiButton__text'); + for (const value of Nodes) { + $.push(await value._webElement.getText()); + } + for (let i = 0; i < $.length; i++) { + expect(tableData[i + 1][0]).to.eql($[i]); + } + await testSubjects.click('zoom-in'); + }); + + it('resolver Nodes navigation Up', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('north-button'); + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 0; i < OriginalNodeDataStyle.length; i++) { + expect(parseFloat(OriginalNodeDataStyle[i].top)).to.lessThan( + parseFloat(NewNodeDataStyle[i].top) + ); + expect(parseFloat(OriginalNodeDataStyle[i].left)).to.equal( + parseFloat(NewNodeDataStyle[i].left) + ); + } + await testSubjects.click('center-button'); + }); + + it('resolver Nodes navigation Down', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('south-button'); + + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 0; i < NewNodeDataStyle.length; i++) { + expect(parseFloat(NewNodeDataStyle[i].top)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].top) + ); + expect(parseFloat(OriginalNodeDataStyle[i].left)).to.equal( + parseFloat(NewNodeDataStyle[i].left) + ); + } + await testSubjects.click('center-button'); + }); + + it('resolver Nodes navigation Right', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('west-button'); + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 0; i < NewNodeDataStyle.length; i++) { + expect(parseFloat(OriginalNodeDataStyle[i].left)).to.lessThan( + parseFloat(NewNodeDataStyle[i].left) + ); + expect(parseFloat(NewNodeDataStyle[i].top)).to.equal( + parseFloat(OriginalNodeDataStyle[i].top) + ); + } + await testSubjects.click('center-button'); + }); + + it('resolver Nodes navigation Left', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('east-button'); + + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 0; i < OriginalNodeDataStyle.length; i++) { + expect(parseFloat(NewNodeDataStyle[i].left)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].left) + ); + expect(parseFloat(NewNodeDataStyle[i].top)).to.equal( + parseFloat(OriginalNodeDataStyle[i].top) + ); + } + await testSubjects.click('center-button'); + }); + + it('resolver Nodes navigation Center', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('east-button'); + await testSubjects.click('south-button'); + + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 0; i < NewNodeDataStyle.length; i++) { + expect(parseFloat(NewNodeDataStyle[i].left)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].left) + ); + expect(parseFloat(NewNodeDataStyle[i].top)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].top) + ); + } + await (await testSubjects.find('center-button')).click(); + const CenterNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + + for (let i = 0; i < CenterNodeDataStyle.length; i++) { + expect(parseFloat(CenterNodeDataStyle[i].left)).to.equal( + parseFloat(OriginalNodeDataStyle[i].left) + ); + expect(parseFloat(CenterNodeDataStyle[i].top)).to.equal( + parseFloat(OriginalNodeDataStyle[i].top) + ); + } + }); + + it('resolver Nodes navigation zoom in', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('zoom-in'); + const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 1; i < NewNodeDataStyle.length; i++) { + expect(parseFloat(OriginalNodeDataStyle[i].left)).to.lessThan( + parseFloat(NewNodeDataStyle[i].left) + ); + expect(parseFloat(OriginalNodeDataStyle[i].top)).to.lessThan( + parseFloat(NewNodeDataStyle[i].top) + ); + expect(parseFloat(OriginalNodeDataStyle[i].width)).to.lessThan( + parseFloat(NewNodeDataStyle[i].width) + ); + expect(parseFloat(OriginalNodeDataStyle[i].height)).to.lessThan( + parseFloat(NewNodeDataStyle[i].height) + ); + await testSubjects.click('zoom-out'); + } + }); + + it('resolver Nodes navigation zoom out', async () => { + const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + await testSubjects.click('zoom-out'); + const NewNodeDataStyle1 = await pageObjects.endpointAlerts.parseStyles( + 'resolverNode', + 'style' + ); + for (let i = 1; i < OriginalNodeDataStyle.length; i++) { + expect(parseFloat(NewNodeDataStyle1[i].left)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].left) + ); + expect(parseFloat(NewNodeDataStyle1[i].top)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].top) + ); + expect(parseFloat(NewNodeDataStyle1[i].width)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].width) + ); + expect(parseFloat(NewNodeDataStyle1[i].height)).to.lessThan( + parseFloat(OriginalNodeDataStyle[i].height) + ); + } + await testSubjects.click('zoom-in'); + }); + + after(async () => { + await browser.setWindowSize(1600, 1000); + await testSubjects.click('euiFlyoutCloseButton'); + await pageObjects.common.sleep(2000); + await esArchiver.unload('endpoint/resolver_tree/api_feature'); + }); + }); +} diff --git a/x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts b/x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts index a5ad45536de89..ff675f151c087 100644 --- a/x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts +++ b/x-pack/test/functional_endpoint/page_objects/endpoint_alerts_page.ts @@ -5,16 +5,48 @@ */ import { FtrProviderContext } from '../ftr_provider_context'; +import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; export function EndpointAlertsPageProvider({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + /** + * @function parseStyles + * Parses a string of inline styles into a javascript object with casing for react + * + * @param {string} styles + * @returns {Object} + */ + const parseStyle = (styles: any) => + styles + .split(';') + .filter((style: any) => style.split(':')[0] && style.split(':')[1]) + .map((style: any) => [ + style + .split(':')[0] + .trim() + .replace(/-./g, (c: any) => c.substr(1).toUpperCase()), + style + .split(':') + .slice(1) + .join(':') + .trim(), + ]) + .reduce( + (styleObj: any, style: any) => ({ + ...styleObj, + [style[0]]: style[1], + }), + {} + ); return { async enterSearchBarQuery(query: string) { return await testSubjects.setValue('alertsSearchBar', query, { clearWithKeyboard: true }); }, async submitSearchBarFilter() { - return await testSubjects.click('querySubmitButton'); + return testSubjects.click('querySubmitButton'); }, async setSearchBarDate(timestamp: string) { await testSubjects.click('superDatePickerShowDatesButton'); @@ -23,5 +55,70 @@ export function EndpointAlertsPageProvider({ getService }: FtrProviderContext) { await testSubjects.setValue('superDatePickerAbsoluteDateInput', timestamp); await this.submitSearchBarFilter(); }, + /** + * Finds a table and returns the data in a nested array with row 0 is the headers if they exist. + * It uses euiTableCellContent to avoid poluting the array data with the euiTableRowCell__mobileHeader data. + * @param dataTestSubj + * @param element + * @returns Promise + */ + async getEndpointAlertResolverTableData(dataTestSubj: string, element: string) { + await testSubjects.exists(dataTestSubj); + const hostTable: WebElementWrapper = await testSubjects.find(dataTestSubj); + const $ = await hostTable.parseDomContent(); + return $(element) + .toArray() + .map(row => + $(row) + .find('.euiTableCellContent') + .toArray() + .map(cell => + $(cell) + .text() + .replace(/ /g, '') + .trim() + ) + ); + }, + /** + * Finds a nodes and returns the data in a nested array of nodes. + * @param dataTestSubj + * @param element + * @returns Promise + */ + async getEndpointAlertResolverNodeData(dataTestSubj: string, element: string) { + await testSubjects.exists(dataTestSubj); + const Elements = await testSubjects.findAll(dataTestSubj); + const $ = []; + for (const value of Elements) { + $.push(await value.getAttribute(element)); + } + return $; + }, + /** + * Gets a array of not parsed styles and returns the Array of parsed styles. + * @returns Promise + * @param dataTestSubj + * @param element + */ + async parseStyles(dataTestSubj: string, element: string) { + const tableData = await this.getEndpointAlertResolverNodeData(dataTestSubj, element); + const $ = []; + for (let i = 1; i < tableData.length; i++) { + const eachStyle = parseStyle(tableData[i]); + $.push(eachStyle); + } + return $; + }, + + async waitForTableToHaveData(dataTestSubj: string) { + await retry.waitForWithTimeout('table to have data', 2000, async () => { + const tableData = await this.getEndpointAlertResolverTableData(dataTestSubj, 'tr'); + if (tableData[1][0] === 'No items found') { + return false; + } + return true; + }); + }, }; } From 932d6ad214a879ddf398438d321ec865776a592f Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 5 May 2020 14:56:31 -0600 Subject: [PATCH 40/72] [Maps] do not show auto-clustering capabilities for a geo_shape source (#65306) * [Maps] do not show auto-clustering capabilities for a geo_shape source * add check in UpdateSourceEditor --- .../plugins/maps/public/index_pattern_util.js | 20 +++++++++++-------- .../create_source_editor.js | 9 +++------ .../es_pew_pew_source/create_source_editor.js | 9 +++------ .../es_search_source/create_source_editor.js | 15 +++++--------- .../es_search_source/update_source_editor.js | 4 ++-- 5 files changed, 25 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/maps/public/index_pattern_util.js b/x-pack/plugins/maps/public/index_pattern_util.js index 6cb02c7605e28..bbea4a9e3ab2a 100644 --- a/x-pack/plugins/maps/public/index_pattern_util.js +++ b/x-pack/plugins/maps/public/index_pattern_util.js @@ -32,14 +32,18 @@ export function getTermsFields(fields) { export const AGGREGATABLE_GEO_FIELD_TYPES = [ES_GEO_FIELD_TYPE.GEO_POINT]; -export function getAggregatableGeoFields(fields) { - return fields.filter(field => { - return ( - field.aggregatable && - !indexPatterns.isNestedField(field) && - AGGREGATABLE_GEO_FIELD_TYPES.includes(field.type) - ); - }); +export function getFieldsWithGeoTileAgg(fields) { + return fields.filter(supportsGeoTileAgg); +} + +export function supportsGeoTileAgg(field) { + // TODO add geo_shape support with license check + return ( + field && + field.aggregatable && + !indexPatterns.isNestedField(field) && + field.type === ES_GEO_FIELD_TYPE.GEO_POINT + ); } // Returns filtered fields list containing only fields that exist in _source. diff --git a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js index 265606dc87e0f..77d2ffb8c577e 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_geo_grid_source/create_source_editor.js @@ -14,10 +14,7 @@ import { NoIndexPatternCallout } from '../../../components/no_index_pattern_call import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSpacer } from '@elastic/eui'; -import { - AGGREGATABLE_GEO_FIELD_TYPES, - getAggregatableGeoFields, -} from '../../../index_pattern_util'; +import { AGGREGATABLE_GEO_FIELD_TYPES, getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; import { RenderAsSelect } from './render_as_select'; export class CreateSourceEditor extends Component { @@ -90,7 +87,7 @@ export class CreateSourceEditor extends Component { }); //make default selection - const geoFields = getAggregatableGeoFields(indexPattern.fields); + const geoFields = getFieldsWithGeoTileAgg(indexPattern.fields); if (geoFields[0]) { this._onGeoFieldSelect(geoFields[0].name); } @@ -145,7 +142,7 @@ export class CreateSourceEditor extends Component { onChange={this._onGeoFieldSelect} fields={ this.state.indexPattern - ? getAggregatableGeoFields(this.state.indexPattern.fields) + ? getFieldsWithGeoTileAgg(this.state.indexPattern.fields) : undefined } /> diff --git a/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js index a4af1a3c19c83..78c16130891b8 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_pew_pew_source/create_source_editor.js @@ -14,10 +14,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiFormRow, EuiCallOut } from '@elastic/eui'; -import { - AGGREGATABLE_GEO_FIELD_TYPES, - getAggregatableGeoFields, -} from '../../../index_pattern_util'; +import { AGGREGATABLE_GEO_FIELD_TYPES, getFieldsWithGeoTileAgg } from '../../../index_pattern_util'; export class CreateSourceEditor extends Component { static propTypes = { @@ -86,7 +83,7 @@ export class CreateSourceEditor extends Component { return; } - const geoFields = getAggregatableGeoFields(indexPattern.fields); + const geoFields = getFieldsWithGeoTileAgg(indexPattern.fields); this.setState({ isLoadingIndexPattern: false, indexPattern: indexPattern, @@ -128,7 +125,7 @@ export class CreateSourceEditor extends Component { } const fields = this.state.indexPattern - ? getAggregatableGeoFields(this.state.indexPattern.fields) + ? getFieldsWithGeoTileAgg(this.state.indexPattern.fields) : undefined; return ( diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js index aeb3835354f07..3a25bd90384e9 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/create_source_editor.js @@ -17,7 +17,7 @@ import { ES_GEO_FIELD_TYPE, SCALING_TYPES } from '../../../../common/constants'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { indexPatterns } from '../../../../../../../src/plugins/data/public'; import { ScalingForm } from './scaling_form'; -import { getTermsFields } from '../../../index_pattern_util'; +import { getTermsFields, supportsGeoTileAgg } from '../../../index_pattern_util'; function getGeoFields(fields) { return fields.filter(field => { @@ -28,13 +28,8 @@ function getGeoFields(fields) { }); } -function isGeoFieldAggregatable(indexPattern, geoFieldName) { - if (!indexPattern) { - return false; - } - - const geoField = indexPattern.fields.getByName(geoFieldName); - return geoField && geoField.aggregatable; +function doesGeoFieldSupportGeoTileAgg(indexPattern, geoFieldName) { + return indexPattern ? supportsGeoTileAgg(indexPattern.fields.getByName(geoFieldName)) : false; } const RESET_INDEX_PATTERN_STATE = { @@ -133,7 +128,7 @@ export class CreateSourceEditor extends Component { // Respect previous scaling type selection unless newly selected geo field does not support clustering. const scalingType = this.state.scalingType === SCALING_TYPES.CLUSTERS && - !isGeoFieldAggregatable(this.state.indexPattern, geoFieldName) + !doesGeoFieldSupportGeoTileAgg(this.state.indexPattern, geoFieldName) ? SCALING_TYPES.LIMIT : this.state.scalingType; this.setState( @@ -218,7 +213,7 @@ export class CreateSourceEditor extends Component { indexPatternId={this.state.indexPatternId} onChange={this._onScalingPropChange} scalingType={this.state.scalingType} - supportsClustering={isGeoFieldAggregatable( + supportsClustering={doesGeoFieldSupportGeoTileAgg( this.state.indexPattern, this.state.geoFieldName )} diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js b/x-pack/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js index cb6255afd0a42..59b41c2a79532 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/update_source_editor.js @@ -12,7 +12,7 @@ import { TooltipSelector } from '../../../components/tooltip_selector'; import { getIndexPatternService } from '../../../kibana_services'; import { i18n } from '@kbn/i18n'; -import { getTermsFields, getSourceFields } from '../../../index_pattern_util'; +import { getTermsFields, getSourceFields, supportsGeoTileAgg } from '../../../index_pattern_util'; import { SORT_ORDER } from '../../../../common/constants'; import { ESDocField } from '../../fields/es_doc_field'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -90,7 +90,7 @@ export class UpdateSourceEditor extends Component { }); this.setState({ - supportsClustering: geoField.aggregatable, + supportsClustering: supportsGeoTileAgg(geoField), sourceFields: sourceFields, termFields: getTermsFields(indexPattern.fields), //todo change term fields to use fields sortFields: indexPattern.fields.filter( From 5bad855e4b759a3bb486349b1bbbaf7a56d4fffe Mon Sep 17 00:00:00 2001 From: Devon Thomson Date: Tue, 5 May 2020 16:58:36 -0400 Subject: [PATCH 41/72] Return to dashboard after editing embeddable (#62865) Changed the process for saving visualizations and lens visualizations when the user has been redirected there from another application. --- .../viewport/dashboard_viewport.test.tsx | 3 +- .../tests/dashboard_container.test.tsx | 5 +- .../dashboard/public/dashboard_constants.ts | 1 - src/plugins/embeddable/public/index.ts | 1 + .../lib/actions/edit_panel_action.test.tsx | 12 +- .../public/lib/actions/edit_panel_action.ts | 22 ++- .../lib/panel/embeddable_panel.test.tsx | 12 +- src/plugins/embeddable/public/types.ts | 2 + src/plugins/saved_objects/public/index.ts | 9 +- .../saved_objects/public/save_modal/index.ts | 3 +- .../save_modal/saved_object_save_modal.tsx | 13 +- .../saved_object_save_modal_origin.tsx | 117 ++++++++++++ .../visualize_embeddable_factory.tsx | 18 +- src/plugins/visualizations/public/mocks.ts | 3 +- src/plugins/visualizations/public/plugin.ts | 10 +- .../public/wizard/new_vis_modal.test.tsx | 6 +- .../public/wizard/new_vis_modal.tsx | 8 +- .../public/application/editor/editor.js | 107 +++++++---- .../application/editor/lib/url_helper.ts | 6 +- .../dashboard/create_and_add_embeddables.js | 6 +- .../dashboard/edit_embeddable_redirects.js | 79 ++++++++ test/functional/apps/dashboard/index.js | 1 + test/functional/apps/dashboard/view_edit.js | 5 +- .../functional/page_objects/visualize_page.ts | 38 +++- .../services/dashboard/visualizations.js | 5 +- test/functional/services/test_subjects.ts | 18 +- .../lens/public/app_plugin/app.test.tsx | 41 ++--- x-pack/plugins/lens/public/app_plugin/app.tsx | 172 +++++++++++------- .../lens/public/app_plugin/mounter.tsx | 57 ++++-- .../plugins/lens/public/helpers/url_helper.ts | 6 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../dashboard_mode/dashboard_empty_screen.js | 39 +++- .../test/functional/page_objects/lens_page.ts | 19 +- 34 files changed, 650 insertions(+), 198 deletions(-) create mode 100644 src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx create mode 100644 test/functional/apps/dashboard/edit_embeddable_redirects.js diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx index 4f9aa75f52105..b3fc462fd1c50 100644 --- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx +++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.test.tsx @@ -34,6 +34,7 @@ import { import { KibanaContextProvider } from '../../../../../kibana_react/public'; // eslint-disable-next-line import { embeddablePluginMock } from 'src/plugins/embeddable/public/mocks'; +import { applicationServiceMock } from '../../../../../../core/public/mocks'; let dashboardContainer: DashboardContainer | undefined; @@ -50,7 +51,7 @@ function getProps( const start = doStart(); const options: DashboardContainerOptions = { - application: {} as any, + application: applicationServiceMock.createStartContract(), embeddable: { getTriggerCompatibleActions: (() => []) as any, getEmbeddableFactories: start.getEmbeddableFactories, diff --git a/src/plugins/dashboard/public/application/tests/dashboard_container.test.tsx b/src/plugins/dashboard/public/application/tests/dashboard_container.test.tsx index 40231de7597f1..6eb85faeea014 100644 --- a/src/plugins/dashboard/public/application/tests/dashboard_container.test.tsx +++ b/src/plugins/dashboard/public/application/tests/dashboard_container.test.tsx @@ -38,6 +38,7 @@ import { embeddablePluginMock } from '../../../../embeddable/public/mocks'; import { inspectorPluginMock } from '../../../../inspector/public/mocks'; import { KibanaContextProvider } from '../../../../kibana_react/public'; import { uiActionsPluginMock } from '../../../../ui_actions/public/mocks'; +import { applicationServiceMock } from '../../../../../core/public/mocks'; test('DashboardContainer in edit mode shows edit mode actions', async () => { const inspector = inspectorPluginMock.createStartContract(); @@ -56,7 +57,7 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => { const initialInput = getSampleDashboardInput({ viewMode: ViewMode.VIEW }); const options: DashboardContainerOptions = { - application: {} as any, + application: applicationServiceMock.createStartContract(), embeddable: start, notifications: {} as any, overlays: {} as any, @@ -84,7 +85,7 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => { getAllEmbeddableFactories={(() => []) as any} getEmbeddableFactory={(() => null) as any} notifications={{} as any} - application={{} as any} + application={options.application} overlays={{} as any} inspector={inspector} SavedObjectFinder={() => null} diff --git a/src/plugins/dashboard/public/dashboard_constants.ts b/src/plugins/dashboard/public/dashboard_constants.ts index 0820ebd371004..490ddbed933d9 100644 --- a/src/plugins/dashboard/public/dashboard_constants.ts +++ b/src/plugins/dashboard/public/dashboard_constants.ts @@ -18,7 +18,6 @@ */ export const DashboardConstants = { - ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM: 'addToDashboard', LANDING_PAGE_PATH: '/dashboards', CREATE_NEW_DASHBOARD_URL: '/dashboard', ADD_EMBEDDABLE_ID: 'addEmbeddableId', diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts index e61ad2a6eefed..84c6eea7c4ff1 100644 --- a/src/plugins/embeddable/public/index.ts +++ b/src/plugins/embeddable/public/index.ts @@ -22,6 +22,7 @@ import './index.scss'; import { PluginInitializerContext } from 'src/core/public'; import { EmbeddablePublicPlugin } from './plugin'; +export { EMBEDDABLE_ORIGINATING_APP_PARAM } from './types'; export { ACTION_ADD_PANEL, ACTION_APPLY_FILTER, diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx index fc5438b8c8dcb..196bd593eb8d5 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.test.tsx @@ -22,10 +22,12 @@ import { Embeddable, EmbeddableInput } from '../embeddables'; import { ViewMode } from '../types'; import { ContactCardEmbeddable } from '../test_samples'; import { embeddablePluginMock } from '../../mocks'; +import { applicationServiceMock } from '../../../../../core/public/mocks'; const { doStart } = embeddablePluginMock.createInstance(); const start = doStart(); const getFactory = start.getEmbeddableFactory; +const applicationMock = applicationServiceMock.createStartContract(); class EditableEmbeddable extends Embeddable { public readonly type = 'EDITABLE_EMBEDDABLE'; @@ -41,7 +43,7 @@ class EditableEmbeddable extends Embeddable { } test('is compatible when edit url is available, in edit mode and editable', async () => { - const action = new EditPanelAction(getFactory, {} as any); + const action = new EditPanelAction(getFactory, applicationMock); expect( await action.isCompatible({ embeddable: new EditableEmbeddable({ id: '123', viewMode: ViewMode.EDIT }, true), @@ -50,7 +52,7 @@ test('is compatible when edit url is available, in edit mode and editable', asyn }); test('getHref returns the edit urls', async () => { - const action = new EditPanelAction(getFactory, {} as any); + const action = new EditPanelAction(getFactory, applicationMock); expect(action.getHref).toBeDefined(); if (action.getHref) { @@ -64,7 +66,7 @@ test('getHref returns the edit urls', async () => { }); test('is not compatible when edit url is not available', async () => { - const action = new EditPanelAction(getFactory, {} as any); + const action = new EditPanelAction(getFactory, applicationMock); const embeddable = new ContactCardEmbeddable( { id: '123', @@ -83,7 +85,7 @@ test('is not compatible when edit url is not available', async () => { }); test('is not visible when edit url is available but in view mode', async () => { - const action = new EditPanelAction(getFactory, {} as any); + const action = new EditPanelAction(getFactory, applicationMock); expect( await action.isCompatible({ embeddable: new EditableEmbeddable( @@ -98,7 +100,7 @@ test('is not visible when edit url is available but in view mode', async () => { }); test('is not compatible when edit url is available, in edit mode, but not editable', async () => { - const action = new EditPanelAction(getFactory, {} as any); + const action = new EditPanelAction(getFactory, applicationMock); expect( await action.isCompatible({ embeddable: new EditableEmbeddable( diff --git a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts index d57867900c24b..d1edddb2aa86b 100644 --- a/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts +++ b/src/plugins/embeddable/public/lib/actions/edit_panel_action.ts @@ -20,10 +20,11 @@ import { i18n } from '@kbn/i18n'; import { ApplicationStart } from 'kibana/public'; import { Action } from 'src/plugins/ui_actions/public'; +import { take } from 'rxjs/operators'; import { ViewMode } from '../types'; import { EmbeddableFactoryNotFoundError } from '../errors'; -import { IEmbeddable } from '../embeddables'; import { EmbeddableStart } from '../../plugin'; +import { EMBEDDABLE_ORIGINATING_APP_PARAM, IEmbeddable } from '../..'; export const ACTION_EDIT_PANEL = 'editPanel'; @@ -35,11 +36,18 @@ export class EditPanelAction implements Action { public readonly type = ACTION_EDIT_PANEL; public readonly id = ACTION_EDIT_PANEL; public order = 50; + public currentAppId: string | undefined; constructor( private readonly getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'], private readonly application: ApplicationStart - ) {} + ) { + if (this.application?.currentAppId$) { + this.application.currentAppId$ + .pipe(take(1)) + .subscribe((appId: string | undefined) => (this.currentAppId = appId)); + } + } public getDisplayName({ embeddable }: ActionContext) { const factory = this.getEmbeddableFactory(embeddable.type); @@ -93,7 +101,15 @@ export class EditPanelAction implements Action { } public async getHref({ embeddable }: ActionContext): Promise { - const editUrl = embeddable ? embeddable.getOutput().editUrl : undefined; + let editUrl = embeddable ? embeddable.getOutput().editUrl : undefined; + if (editUrl && this.currentAppId) { + editUrl += `?${EMBEDDABLE_ORIGINATING_APP_PARAM}=${this.currentAppId}`; + + // TODO: Remove this after https://github.com/elastic/kibana/pull/63443 + if (this.currentAppId === 'kibana') { + editUrl += `:${window.location.hash.split(/[\/\?]/)[1]}`; + } + } return editUrl ? editUrl : ''; } } diff --git a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx index 9dd4c74c624d9..384297d8dee7d 100644 --- a/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx +++ b/src/plugins/embeddable/public/lib/panel/embeddable_panel.test.tsx @@ -44,6 +44,7 @@ import { import { inspectorPluginMock } from '../../../../inspector/public/mocks'; import { EuiBadge } from '@elastic/eui'; import { embeddablePluginMock } from '../../mocks'; +import { applicationServiceMock } from '../../../../../core/public/mocks'; const actionRegistry = new Map(); const triggerRegistry = new Map(); @@ -55,6 +56,7 @@ const trigger: Trigger = { id: CONTEXT_MENU_TRIGGER, }; const embeddableFactory = new ContactCardEmbeddableFactory((() => null) as any, {} as any); +const applicationMock = applicationServiceMock.createStartContract(); actionRegistry.set(editModeAction.id, editModeAction); triggerRegistry.set(trigger.id, trigger); @@ -159,7 +161,7 @@ test('HelloWorldContainer in view mode hides edit mode actions', async () => { getAllEmbeddableFactories={start.getEmbeddableFactories} getEmbeddableFactory={start.getEmbeddableFactory} notifications={{} as any} - application={{} as any} + application={applicationMock} overlays={{} as any} inspector={inspector} SavedObjectFinder={() => null} @@ -199,7 +201,7 @@ const renderInEditModeAndOpenContextMenu = async ( getEmbeddableFactory={start.getEmbeddableFactory} notifications={{} as any} overlays={{} as any} - application={{} as any} + application={applicationMock} inspector={inspector} SavedObjectFinder={() => null} /> @@ -306,7 +308,7 @@ test('HelloWorldContainer in edit mode shows edit mode actions', async () => { getEmbeddableFactory={start.getEmbeddableFactory} notifications={{} as any} overlays={{} as any} - application={{} as any} + application={applicationMock} inspector={inspector} SavedObjectFinder={() => null} /> @@ -369,7 +371,7 @@ test('Updates when hidePanelTitles is toggled', async () => { getEmbeddableFactory={start.getEmbeddableFactory} notifications={{} as any} overlays={{} as any} - application={{} as any} + application={applicationMock} inspector={inspector} SavedObjectFinder={() => null} /> @@ -422,7 +424,7 @@ test('Check when hide header option is false', async () => { getEmbeddableFactory={start.getEmbeddableFactory} notifications={{} as any} overlays={{} as any} - application={{} as any} + application={applicationMock} inspector={inspector} SavedObjectFinder={() => null} hideHeader={false} diff --git a/src/plugins/embeddable/public/types.ts b/src/plugins/embeddable/public/types.ts index 2d112b2359818..a57af862f2a34 100644 --- a/src/plugins/embeddable/public/types.ts +++ b/src/plugins/embeddable/public/types.ts @@ -26,6 +26,8 @@ import { EmbeddableFactoryDefinition, } from './lib/embeddables'; +export const EMBEDDABLE_ORIGINATING_APP_PARAM = 'embeddableOriginatingApp'; + export type EmbeddableFactoryRegistry = Map; export type EmbeddableFactoryProvider = < diff --git a/src/plugins/saved_objects/public/index.ts b/src/plugins/saved_objects/public/index.ts index 9e0a7c40c043f..e38a0ef9830ea 100644 --- a/src/plugins/saved_objects/public/index.ts +++ b/src/plugins/saved_objects/public/index.ts @@ -19,7 +19,14 @@ import { SavedObjectsPublicPlugin } from './plugin'; -export { OnSaveProps, SavedObjectSaveModal, SaveResult, showSaveModal } from './save_modal'; +export { + OnSaveProps, + SavedObjectSaveModal, + SavedObjectSaveModalOrigin, + SaveModalState, + SaveResult, + showSaveModal, +} from './save_modal'; export { getSavedObjectFinder, SavedObjectFinderUi, SavedObjectMetaData } from './finder'; export { SavedObjectLoader, diff --git a/src/plugins/saved_objects/public/save_modal/index.ts b/src/plugins/saved_objects/public/save_modal/index.ts index f26aa732f30a1..7c32337bb314a 100644 --- a/src/plugins/saved_objects/public/save_modal/index.ts +++ b/src/plugins/saved_objects/public/save_modal/index.ts @@ -17,5 +17,6 @@ * under the License. */ -export { SavedObjectSaveModal, OnSaveProps } from './saved_object_save_modal'; +export { SavedObjectSaveModal, OnSaveProps, SaveModalState } from './saved_object_save_modal'; +export { SavedObjectSaveModalOrigin } from './saved_object_save_modal_origin'; export { showSaveModal, SaveResult } from './show_saved_object_save_modal'; diff --git a/src/plugins/saved_objects/public/save_modal/saved_object_save_modal.tsx b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal.tsx index 95eb56c0e874b..962f993633e6f 100644 --- a/src/plugins/saved_objects/public/save_modal/saved_object_save_modal.tsx +++ b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal.tsx @@ -53,14 +53,15 @@ interface Props { onClose: () => void; title: string; showCopyOnSave: boolean; + initialCopyOnSave?: boolean; objectType: string; confirmButtonLabel?: React.ReactNode; - options?: React.ReactNode; + options?: React.ReactNode | ((state: SaveModalState) => React.ReactNode); description?: string; showDescription: boolean; } -interface State { +export interface SaveModalState { title: string; copyOnSave: boolean; isTitleDuplicateConfirmed: boolean; @@ -71,11 +72,11 @@ interface State { const generateId = htmlIdGenerator(); -export class SavedObjectSaveModal extends React.Component { +export class SavedObjectSaveModal extends React.Component { private warning = React.createRef(); public readonly state = { title: this.props.title, - copyOnSave: false, + copyOnSave: Boolean(this.props.initialCopyOnSave), isTitleDuplicateConfirmed: false, hasTitleDuplicate: false, isLoading: false, @@ -139,7 +140,9 @@ export class SavedObjectSaveModal extends React.Component { {this.renderViewDescription()} - {this.props.options} + {typeof this.props.options === 'function' + ? this.props.options(this.state) + : this.props.options} diff --git a/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx new file mode 100644 index 0000000000000..34f4bc593fdc4 --- /dev/null +++ b/src/plugins/saved_objects/public/save_modal/saved_object_save_modal_origin.tsx @@ -0,0 +1,117 @@ +/* + * 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, { Fragment, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFormRow, EuiSwitch } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import { OnSaveProps, SaveModalState, SavedObjectSaveModal } from '.'; + +interface SaveModalDocumentInfo { + id?: string; + title: string; + description?: string; +} + +interface OriginSaveModalProps { + originatingApp?: string; + documentInfo: SaveModalDocumentInfo; + objectType: string; + onClose: () => void; + onSave: (props: OnSaveProps & { returnToOrigin: boolean }) => void; +} + +export function SavedObjectSaveModalOrigin(props: OriginSaveModalProps) { + const [returnToOriginMode, setReturnToOriginMode] = useState(Boolean(props.originatingApp)); + const { documentInfo } = props; + + const returnLabel = i18n.translate('savedObjects.saveModalOrigin.returnToOriginLabel', { + defaultMessage: 'Return', + }); + const addLabel = i18n.translate('savedObjects.saveModalOrigin.addToOriginLabel', { + defaultMessage: 'Add', + }); + + const getReturnToOriginSwitch = (state: SaveModalState) => { + if (!props.originatingApp) { + return; + } + let origin = props.originatingApp!; + + // TODO: Remove this after https://github.com/elastic/kibana/pull/63443 + if (origin.startsWith('kibana:')) { + origin = origin.split(':')[1]; + } + + if ( + !state.copyOnSave || + origin === 'dashboard' // dashboard supports adding a copied panel on save... + ) { + const originVerb = !documentInfo.id || state.copyOnSave ? addLabel : returnLabel; + return ( + + + { + setReturnToOriginMode(event.target.checked); + }} + label={ + + } + /> + + + ); + } else { + setReturnToOriginMode(false); + } + }; + + const onModalSave = (onSaveProps: OnSaveProps) => { + props.onSave({ ...onSaveProps, returnToOrigin: returnToOriginMode }); + }; + + const confirmButtonLabel = returnToOriginMode + ? i18n.translate('savedObjects.saveModalOrigin.saveAndReturnLabel', { + defaultMessage: 'Save and return', + }) + : null; + + return ( + + ); +} diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 6ab1c98645988..c6d43a4ef2f80 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -19,12 +19,14 @@ import { i18n } from '@kbn/i18n'; import { SavedObjectMetaData } from 'src/plugins/saved_objects/public'; +import { first } from 'rxjs/operators'; import { SavedObjectAttributes } from '../../../../core/public'; import { EmbeddableFactoryDefinition, EmbeddableOutput, ErrorEmbeddable, IContainer, + EMBEDDABLE_ORIGINATING_APP_PARAM, } from '../../../embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; @@ -59,6 +61,7 @@ export class VisualizeEmbeddableFactory VisualizationAttributes > { public readonly type = VISUALIZE_EMBEDDABLE_TYPE; + public readonly savedObjectMetaData: SavedObjectMetaData = { name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }), includeFields: ['visState'], @@ -98,6 +101,18 @@ export class VisualizeEmbeddableFactory }); } + public async getCurrentAppId() { + let currentAppId = await this.deps + .start() + .core.application.currentAppId$.pipe(first()) + .toPromise(); + // TODO: Remove this after https://github.com/elastic/kibana/pull/63443 + if (currentAppId === 'kibana') { + currentAppId += `:${window.location.hash.split(/[\/\?]/)[1]}`; + } + return currentAppId; + } + public async createFromSavedObject( savedObjectId: string, input: Partial & { id: string }, @@ -118,8 +133,9 @@ export class VisualizeEmbeddableFactory public async create() { // TODO: This is a bit of a hack to preserve the original functionality. Ideally we will clean this up // to allow for in place creation of visualizations without having to navigate away to a new URL. + const originatingAppParam = await this.getCurrentAppId(); showNewVisModal({ - editorParams: ['addToDashboard'], + editorParams: [`${EMBEDDABLE_ORIGINATING_APP_PARAM}=${originatingAppParam}`], }); return undefined; } diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index d6eeffdb01459..70c3bc2c1ed05 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from '../../../core/public'; import { VisualizationsSetup, VisualizationsStart } from './'; import { VisualizationsPlugin } from './plugin'; -import { coreMock } from '../../../core/public/mocks'; +import { coreMock, applicationServiceMock } from '../../../core/public/mocks'; import { embeddablePluginMock } from '../../../plugins/embeddable/public/mocks'; import { expressionsPluginMock } from '../../../plugins/expressions/public/mocks'; import { dataPluginMock } from '../../../plugins/data/public/mocks'; @@ -65,6 +65,7 @@ const createInstance = async () => { expressions: expressionsPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), + application: applicationServiceMock.createStartContract(), }); return { diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index b3e8c9b5b61b3..29d66ea963a66 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -17,7 +17,13 @@ * under the License. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + ApplicationStart, +} from '../../../core/public'; import { TypesService, TypesSetup, TypesStart } from './vis_types'; import { setUISettings, @@ -95,6 +101,7 @@ export interface VisualizationsStartDeps { expressions: ExpressionsStart; inspector: InspectorStart; uiActions: UiActionsStart; + application: ApplicationStart; } /** @@ -131,7 +138,6 @@ export class VisualizationsPlugin expressions.registerRenderer(visualizationRenderer); expressions.registerFunction(rangeExpressionFunction); expressions.registerFunction(visDimensionExpressionFunction); - const embeddableFactory = new VisualizeEmbeddableFactory({ start }); embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx index 5637aeafc6f14..2fdbdedd5b590 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx @@ -144,7 +144,7 @@ describe('NewVisModal', () => { isOpen={true} onClose={onClose} visTypesRegistry={visTypes} - editorParams={['foo=true', 'bar=42', 'addToDashboard']} + editorParams={['foo=true', 'bar=42', 'embeddableOriginatingApp=notAnApp']} addBasePath={addBasePath} uiSettings={uiSettings} savedObjects={{} as SavedObjectsStart} @@ -152,7 +152,9 @@ describe('NewVisModal', () => { ); const visButton = wrapper.find('button[data-test-subj="visType-visWithAliasUrl"]'); visButton.simulate('click'); - expect(window.location.assign).toBeCalledWith('testbasepath/aliasUrl?addToDashboard'); + expect(window.location.assign).toBeCalledWith( + 'testbasepath/aliasUrl?embeddableOriginatingApp=notAnApp' + ); expect(onClose).toHaveBeenCalled(); }); diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 448077819bb8d..6fd65da7e88d2 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -28,6 +28,7 @@ import { SearchSelection } from './search_selection'; import { TypeSelection } from './type_selection'; import { TypesStart, VisType, VisTypeAlias } from '../vis_types'; import { UsageCollectionSetup } from '../../../../plugins/usage_collection/public'; +import { EMBEDDABLE_ORIGINATING_APP_PARAM } from '../../../embeddable/public'; interface TypeSelectionProps { isOpen: boolean; @@ -143,8 +144,11 @@ class NewVisModal extends React.Component + param.startsWith(EMBEDDABLE_ORIGINATING_APP_PARAM) + ); + params = originatingAppParam ? `${params}?${originatingAppParam}` : params; } this.props.onClose(); window.location.assign(params); diff --git a/src/plugins/visualize/public/application/editor/editor.js b/src/plugins/visualize/public/application/editor/editor.js index 9ec411a7744bf..bd699c762371c 100644 --- a/src/plugins/visualize/public/application/editor/editor.js +++ b/src/plugins/visualize/public/application/editor/editor.js @@ -25,11 +25,12 @@ import { i18n } from '@kbn/i18n'; import { EventEmitter } from 'events'; import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; import { makeStateful, useVisualizeAppState, addEmbeddableToDashboardUrl } from './lib'; import { VisualizeConstants } from '../visualize_constants'; import { getEditBreadcrumbs } from '../breadcrumbs'; +import { EMBEDDABLE_ORIGINATING_APP_PARAM } from '../../../../embeddable/public'; + import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util'; import { unhashUrl, removeQueryParam } from '../../../../kibana_utils/public'; import { MarkdownSimple, toMountPoint } from '../../../../kibana_react/public'; @@ -38,9 +39,8 @@ import { subscribeWithScope, migrateLegacyQuery, } from '../../../../kibana_legacy/public'; -import { SavedObjectSaveModal, showSaveModal } from '../../../../saved_objects/public'; +import { showSaveModal, SavedObjectSaveModalOrigin } from '../../../../saved_objects/public'; import { esFilters, connectToQueryState, syncQueryStateWithUrl } from '../../../../data/public'; -import { DashboardConstants } from '../../../../dashboard/public'; import { initVisEditorDirective } from './visualization_editor'; import { initVisualizationDirective } from './visualization'; @@ -110,6 +110,11 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState localStorage.get('kibana.userQueryLanguage') || uiSettings.get('search:queryLanguage'), }; + const originatingApp = $route.current.params[EMBEDDABLE_ORIGINATING_APP_PARAM]; + removeQueryParam(history, EMBEDDABLE_ORIGINATING_APP_PARAM); + + $scope.getOriginatingApp = () => originatingApp; + const visStateToEditorState = () => { const savedVisState = visualizations.convertFromSerializedVis(vis.serialize()); return { @@ -144,13 +149,58 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState $scope.embeddableHandler = embeddableHandler; $scope.topNavMenu = [ + ...($scope.getOriginatingApp() && savedVis.id + ? [ + { + id: 'saveAndReturn', + label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', { + defaultMessage: 'Save and return', + }), + emphasize: true, + iconType: 'check', + description: i18n.translate( + 'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel', + { + defaultMessage: 'Finish editing visualization and return to the last app', + } + ), + testId: 'visualizesaveAndReturnButton', + disableButton() { + return Boolean($scope.dirty); + }, + tooltip() { + if ($scope.dirty) { + return i18n.translate( + 'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip', + { + defaultMessage: 'Apply or Discard your changes before finishing', + } + ); + } + }, + run: async () => { + const saveOptions = { + confirmOverwrite: false, + returnToOrigin: true, + }; + return doSave(saveOptions); + }, + }, + ] + : []), ...(visualizeCapabilities.save ? [ { id: 'save', - label: i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', { - defaultMessage: 'save', - }), + label: + savedVis.id && $scope.getOriginatingApp() + ? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', { + defaultMessage: 'save as', + }) + : i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', { + defaultMessage: 'save', + }), + emphasize: !savedVis.id || !$scope.getOriginatingApp(), description: i18n.translate('visualize.topNavMenu.saveVisualizationButtonAriaLabel', { defaultMessage: 'Save Visualization', }), @@ -175,6 +225,7 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState isTitleDuplicateConfirmed, onTitleDuplicate, newDescription, + returnToOrigin, }) => { const currentTitle = savedVis.title; savedVis.title = newTitle; @@ -184,6 +235,7 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState confirmOverwrite: false, isTitleDuplicateConfirmed, onTitleDuplicate, + returnToOrigin, }; return doSave(saveOptions).then(response => { // If the save wasn't successful, put the original values back. @@ -194,23 +246,13 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState }); }; - const confirmButtonLabel = $scope.isAddToDashMode() ? ( - - ) : null; - const saveModal = ( - {}} - title={savedVis.title} - showCopyOnSave={savedVis.id ? true : false} - objectType="visualization" - confirmButtonLabel={confirmButtonLabel} - description={savedVis.description} - showDescription={true} + originatingApp={$scope.getOriginatingApp()} /> ); showSaveModal(saveModal, I18nContext); @@ -398,12 +440,6 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState $scope.refreshInterval = timefilter.getRefreshInterval(); handleLinkedSearch(initialState.linked); - const addToDashMode = - $route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM]; - removeQueryParam(history, DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM); - - $scope.isAddToDashMode = () => addToDashMode; - $scope.showFilterBar = () => { return vis.type.options.showFilterBar; }; @@ -604,6 +640,7 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState */ function doSave(saveOptions) { // vis.title was not bound and it's needed to reflect title into visState + const firstSave = !Boolean(savedVis.id); stateContainer.transitions.setVis({ title: savedVis.title, type: savedVis.type || stateContainer.getState().vis.type, @@ -631,15 +668,23 @@ function VisualizeAppController($scope, $route, $injector, $timeout, kbnUrlState 'data-test-subj': 'saveVisualizationSuccess', }); - if ($scope.isAddToDashMode()) { + if ($scope.getOriginatingApp() && saveOptions.returnToOrigin) { const appPath = `${VisualizeConstants.EDIT_PATH}/${encodeURIComponent(savedVis.id)}`; + // Manually insert a new url so the back button will open the saved visualization. history.replace(appPath); setActiveUrl(appPath); - - const lastDashboardUrl = chrome.navLinks.get('kibana:dashboard').url; - const dashboardUrl = addEmbeddableToDashboardUrl(lastDashboardUrl, savedVis.id); - history.push(dashboardUrl); + const lastAppType = $scope.getOriginatingApp(); + let href = chrome.navLinks.get(lastAppType).url; + + // TODO: Remove this and use application.redirectTo after https://github.com/elastic/kibana/pull/63443 + if (lastAppType === 'kibana:dashboard') { + const savedVisId = firstSave || savedVis.copyOnSave ? savedVis.id : ''; + href = addEmbeddableToDashboardUrl(href, savedVisId); + history.push(href); + } else { + window.location.href = href; + } } else if (savedVis.id === $route.current.params.id) { chrome.docTitle.change(savedVis.lastSavedTitle); chrome.setBreadcrumbs($injector.invoke(getEditBreadcrumbs)); diff --git a/src/plugins/visualize/public/application/editor/lib/url_helper.ts b/src/plugins/visualize/public/application/editor/lib/url_helper.ts index 84e1ef9687cd0..9f8a0075118ae 100644 --- a/src/plugins/visualize/public/application/editor/lib/url_helper.ts +++ b/src/plugins/visualize/public/application/editor/lib/url_helper.ts @@ -33,8 +33,10 @@ export function addEmbeddableToDashboardUrl(dashboardUrl: string, embeddableId: const { url, query } = parseUrl(dashboardUrl); const [, dashboardId] = url.split(DashboardConstants.CREATE_NEW_DASHBOARD_URL); - query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = VISUALIZE_EMBEDDABLE_TYPE; - query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + if (embeddableId) { + query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = VISUALIZE_EMBEDDABLE_TYPE; + query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + } return `${DashboardConstants.CREATE_NEW_DASHBOARD_URL}${dashboardId}?${stringify(query)}`; } diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.js b/test/functional/apps/dashboard/create_and_add_embeddables.js index 410acdcb5680d..8180051f56e44 100644 --- a/test/functional/apps/dashboard/create_and_add_embeddables.js +++ b/test/functional/apps/dashboard/create_and_add_embeddables.js @@ -48,7 +48,8 @@ export default function({ getService, getPageObjects }) { await PageObjects.visualize.clickAreaChart(); await PageObjects.visualize.clickNewSearch(); await PageObjects.visualize.saveVisualizationExpectSuccess( - 'visualization from top nav add new panel' + 'visualization from top nav add new panel', + { redirectToOrigin: true } ); await retry.try(async () => { const panelCount = await PageObjects.dashboard.getPanelCount(); @@ -64,7 +65,8 @@ export default function({ getService, getPageObjects }) { await PageObjects.visualize.clickAreaChart(); await PageObjects.visualize.clickNewSearch(); await PageObjects.visualize.saveVisualizationExpectSuccess( - 'visualization from add new link' + 'visualization from add new link', + { redirectToOrigin: true } ); await retry.try(async () => { diff --git a/test/functional/apps/dashboard/edit_embeddable_redirects.js b/test/functional/apps/dashboard/edit_embeddable_redirects.js new file mode 100644 index 0000000000000..b45dcc2cedf9b --- /dev/null +++ b/test/functional/apps/dashboard/edit_embeddable_redirects.js @@ -0,0 +1,79 @@ +/* + * 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'; + +export default function({ getService, getPageObjects }) { + const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const dashboardPanelActions = getService('dashboardPanelActions'); + + describe('edit embeddable redirects', () => { + before(async () => { + await esArchiver.load('dashboard/current/kibana'); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.loadSavedDashboard('few panels'); + await PageObjects.dashboard.switchToEditMode(); + }); + + it('redirects via save and return button after edit', async () => { + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.visualize.saveVisualizationAndReturn(); + }); + + it('redirects via save as button after edit, renaming itself', async () => { + const newTitle = 'wowee, looks like I have a new title'; + const originalPanelCount = await PageObjects.dashboard.getPanelCount(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.visualize.saveVisualizationExpectSuccess(newTitle, { + saveAsNew: false, + redirectToOrigin: true, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + const newPanelCount = await PageObjects.dashboard.getPanelCount(); + expect(newPanelCount).to.eql(originalPanelCount); + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles.indexOf(newTitle)).to.not.be(-1); + }); + + it('redirects via save as button after edit, adding a new panel', async () => { + const newTitle = 'wowee, my title just got cooler'; + const originalPanelCount = await PageObjects.dashboard.getPanelCount(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.visualize.saveVisualizationExpectSuccess(newTitle, { + saveAsNew: true, + redirectToOrigin: true, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + const newPanelCount = await PageObjects.dashboard.getPanelCount(); + expect(newPanelCount).to.eql(originalPanelCount + 1); + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles.indexOf(newTitle)).to.not.be(-1); + }); + }); +} diff --git a/test/functional/apps/dashboard/index.js b/test/functional/apps/dashboard/index.js index bd8e6812147e1..3b81a4d974bec 100644 --- a/test/functional/apps/dashboard/index.js +++ b/test/functional/apps/dashboard/index.js @@ -51,6 +51,7 @@ export default function({ getService, loadTestFile }) { loadTestFile(require.resolve('./empty_dashboard')); loadTestFile(require.resolve('./embeddable_rendering')); loadTestFile(require.resolve('./create_and_add_embeddables')); + loadTestFile(require.resolve('./edit_embeddable_redirects')); loadTestFile(require.resolve('./time_zones')); loadTestFile(require.resolve('./dashboard_options')); loadTestFile(require.resolve('./data_shared_attributes')); diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js index a0b972f3ab63c..c8eb10d43ea83 100644 --- a/test/functional/apps/dashboard/view_edit.js +++ b/test/functional/apps/dashboard/view_edit.js @@ -136,7 +136,10 @@ export default function({ getService, getPageObjects }) { await dashboardAddPanel.clickAddNewEmbeddableLink('visualization'); await PageObjects.visualize.clickAreaChart(); await PageObjects.visualize.clickNewSearch(); - await PageObjects.visualize.saveVisualizationExpectSuccess('new viz panel'); + await PageObjects.visualize.saveVisualizationExpectSuccess('new viz panel', { + saveAsNew: false, + redirectToOrigin: true, + }); await PageObjects.dashboard.clickCancelOutOfEditMode(); // for this sleep see https://github.com/elastic/kibana/issues/22299 diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts index 220c2d8f6b363..8fa15fc8268ed 100644 --- a/test/functional/page_objects/visualize_page.ts +++ b/test/functional/page_objects/visualize_page.ts @@ -300,12 +300,25 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide } } - public async saveVisualization(vizName: string, { saveAsNew = false } = {}) { + public async saveVisualization( + vizName: string, + { saveAsNew = false, redirectToOrigin = false } = {} + ) { await this.ensureSavePanelOpen(); await testSubjects.setValue('savedObjectTitle', vizName); - if (saveAsNew) { - log.debug('Check save as new visualization'); - await testSubjects.click('saveAsNewCheckbox'); + + const saveAsNewCheckboxExists = await testSubjects.exists('saveAsNewCheckbox'); + if (saveAsNewCheckboxExists) { + const state = saveAsNew ? 'check' : 'uncheck'; + log.debug('save as new checkbox exists. Setting its state to', state); + await testSubjects.setEuiSwitch('saveAsNewCheckbox', state); + } + + const redirectToOriginCheckboxExists = await testSubjects.exists('returnToOriginModeSwitch'); + if (redirectToOriginCheckboxExists) { + const state = redirectToOrigin ? 'check' : 'uncheck'; + log.debug('redirect to origin checkbox exists. Setting its state to', state); + await testSubjects.setEuiSwitch('returnToOriginModeSwitch', state); } log.debug('Click Save Visualization button'); @@ -320,8 +333,11 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide return message; } - public async saveVisualizationExpectSuccess(vizName: string, { saveAsNew = false } = {}) { - const saveMessage = await this.saveVisualization(vizName, { saveAsNew }); + public async saveVisualizationExpectSuccess( + vizName: string, + { saveAsNew = false, redirectToOrigin = false } = {} + ) { + const saveMessage = await this.saveVisualization(vizName, { saveAsNew, redirectToOrigin }); if (!saveMessage) { throw new Error( `Expected saveVisualization to respond with the saveMessage from the toast, got ${saveMessage}` @@ -331,14 +347,20 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide public async saveVisualizationExpectSuccessAndBreadcrumb( vizName: string, - { saveAsNew = false } = {} + { saveAsNew = false, redirectToOrigin = false } = {} ) { - await this.saveVisualizationExpectSuccess(vizName, { saveAsNew }); + await this.saveVisualizationExpectSuccess(vizName, { saveAsNew, redirectToOrigin }); await retry.waitFor( 'last breadcrumb to have new vis name', async () => (await globalNav.getLastBreadcrumb()) === vizName ); } + + public async saveVisualizationAndReturn() { + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('visualizesaveAndReturnButton'); + await testSubjects.click('visualizesaveAndReturnButton'); + } } return new VisualizePage(); diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js index f7a6fb7d2f694..676e4c384fe36 100644 --- a/test/functional/services/dashboard/visualizations.js +++ b/test/functional/services/dashboard/visualizations.js @@ -116,7 +116,10 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) { await PageObjects.visualize.clickMarkdownWidget(); await PageObjects.visEditor.setMarkdownTxt(markdown); await PageObjects.visEditor.clickGo(); - await PageObjects.visualize.saveVisualizationExpectSuccess(name); + await PageObjects.visualize.saveVisualizationExpectSuccess(name, { + saveAsNew: false, + redirectToOrigin: true, + }); } })(); } diff --git a/test/functional/services/test_subjects.ts b/test/functional/services/test_subjects.ts index e5c2e61c48a0b..090dc995ddc11 100644 --- a/test/functional/services/test_subjects.ts +++ b/test/functional/services/test_subjects.ts @@ -307,6 +307,7 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { await element.scrollIntoViewIfNecessary(); } + // isChecked always returns false when run on an euiSwitch, because they use the aria-checked attribute public async isChecked(selector: string) { const checkbox = await this.find(selector); return await checkbox.isSelected(); @@ -316,7 +317,22 @@ export function TestSubjectsProvider({ getService }: FtrProviderContext) { const isChecked = await this.isChecked(selector); const states = { check: true, uncheck: false }; if (isChecked !== states[state]) { - log.debug(`updating checkbox ${selector}`); + log.debug(`updating checkbox ${selector} from ${isChecked} to ${states[state]}`); + await this.click(selector); + } + } + + public async isEuiSwitchChecked(selector: string) { + const euiSwitch = await this.find(selector); + const isChecked = await euiSwitch.getAttribute('aria-checked'); + return isChecked === 'true'; + } + + public async setEuiSwitch(selector: string, state: 'check' | 'uncheck') { + const isChecked = await this.isEuiSwitchChecked(selector); + const states = { check: true, uncheck: false }; + if (isChecked !== states[state]) { + log.debug(`updating checkbox ${selector} from ${isChecked} to ${states[state]}`); await this.click(selector); } } diff --git a/x-pack/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/plugins/lens/public/app_plugin/app.test.tsx index 41d0e3a7aa9a0..888854a4e83b8 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.test.tsx @@ -104,8 +104,8 @@ describe('Lens App', () => { storage: Storage; docId?: string; docStorage: SavedObjectStore; - redirectTo: (id?: string) => void; - addToDashboardMode?: boolean; + redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; + originatingApp: string | undefined; }> { return ({ navigation: navigationStartMock, @@ -140,7 +140,7 @@ describe('Lens App', () => { load: jest.fn(), save: jest.fn(), }, - redirectTo: jest.fn(id => {}), + redirectTo: jest.fn((id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => {}), } as unknown) as jest.Mocked<{ navigation: typeof navigationStartMock; editorFrame: EditorFrameInstance; @@ -149,8 +149,8 @@ describe('Lens App', () => { storage: Storage; docId?: string; docStorage: SavedObjectStore; - redirectTo: (id?: string) => void; - addToDashboardMode?: boolean; + redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; + originatingApp: string | undefined; }>; } @@ -336,6 +336,7 @@ describe('Lens App', () => { describe('save button', () => { interface SaveProps { newCopyOnSave: boolean; + returnToOrigin?: boolean; newTitle: string; } @@ -347,8 +348,8 @@ describe('Lens App', () => { storage: Storage; docId?: string; docStorage: SavedObjectStore; - redirectTo: (id?: string) => void; - addToDashboardMode?: boolean; + redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; + originatingApp: string | undefined; }>; beforeEach(() => { @@ -374,32 +375,25 @@ describe('Lens App', () => { async function testSave(inst: ReactWrapper, saveProps: SaveProps) { await getButton(inst).run(inst.getDOMNode()); - inst.update(); - - const handler = inst.findWhere(el => el.prop('onSave')).prop('onSave') as ( + const handler = inst.find('[data-test-subj="lnsApp_saveModalOrigin"]').prop('onSave') as ( p: unknown ) => void; handler(saveProps); } async function save({ - initialDocId, - addToDashboardMode, lastKnownDoc = { expression: 'kibana 3' }, + initialDocId, ...saveProps }: SaveProps & { lastKnownDoc?: object; initialDocId?: string; - addToDashboardMode?: boolean; }) { const args = { ...defaultArgs, docId: initialDocId, }; - if (addToDashboardMode) { - args.addToDashboardMode = addToDashboardMode; - } args.editorFrame = frame; (args.docStorage.load as jest.Mock).mockResolvedValue({ id: '1234', @@ -438,7 +432,7 @@ describe('Lens App', () => { expect(getButton(instance).disableButton).toEqual(false); await act(async () => { - testSave(instance, saveProps); + testSave(instance, { ...saveProps }); }); return { args, instance }; @@ -527,7 +521,7 @@ describe('Lens App', () => { expression: 'kibana 3', }); - expect(args.redirectTo).toHaveBeenCalledWith('aaa'); + expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true); inst.setProps({ docId: 'aaa' }); @@ -547,7 +541,7 @@ describe('Lens App', () => { expression: 'kibana 3', }); - expect(args.redirectTo).toHaveBeenCalledWith('aaa'); + expect(args.redirectTo).toHaveBeenCalledWith('aaa', undefined, true); inst.setProps({ docId: 'aaa' }); @@ -601,10 +595,10 @@ describe('Lens App', () => { expect(getButton(instance).disableButton).toEqual(false); }); - it('saves new doc and redirects to dashboard', async () => { + it('saves new doc and redirects to originating app', async () => { const { args } = await save({ initialDocId: undefined, - addToDashboardMode: true, + returnToOrigin: true, newCopyOnSave: false, newTitle: 'hello there', }); @@ -615,7 +609,7 @@ describe('Lens App', () => { title: 'hello there', }); - expect(args.redirectTo).toHaveBeenCalledWith('aaa'); + expect(args.redirectTo).toHaveBeenCalledWith('aaa', true, true); }); it('saves app filters and does not save pinned filters', async () => { @@ -666,7 +660,6 @@ describe('Lens App', () => { }) ); instance.update(); - await act(async () => getButton(instance).run(instance.getDOMNode())); instance.update(); @@ -684,7 +677,7 @@ describe('Lens App', () => { storage: Storage; docId?: string; docStorage: SavedObjectStore; - redirectTo: (id?: string) => void; + redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; }>; beforeEach(() => { diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 28135dd12a724..6b8248fa2030b 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -12,9 +12,11 @@ import { Query, DataPublicPluginStart } from 'src/plugins/data/public'; import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; import { AppMountContext, NotificationsStart } from 'kibana/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; -import { FormattedMessage } from '@kbn/i18n/react'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; -import { SavedObjectSaveModal } from '../../../../../src/plugins/saved_objects/public'; +import { + SavedObjectSaveModalOrigin, + OnSaveProps, +} from '../../../../../src/plugins/saved_objects/public'; import { Document, SavedObjectStore } from '../persistence'; import { EditorFrameInstance } from '../types'; import { NativeRenderer } from '../native_renderer'; @@ -52,7 +54,7 @@ export function App({ docId, docStorage, redirectTo, - addToDashboardMode, + originatingApp, navigation, }: { editorFrame: EditorFrameInstance; @@ -62,8 +64,8 @@ export function App({ storage: IStorageWrapper; docId?: string; docStorage: SavedObjectStore; - redirectTo: (id?: string) => void; - addToDashboardMode?: boolean; + redirectTo: (id?: string, returnToOrigin?: boolean, newlyCreated?: boolean) => void; + originatingApp?: string | undefined; }) { const language = storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage'); @@ -182,6 +184,63 @@ export function App({ lastKnownDoc.expression.length > 0 && core.application.capabilities.visualize.save; + const runSave = ( + saveProps: Omit & { + returnToOrigin: boolean; + } + ) => { + if (!lastKnownDoc) { + return; + } + const [pinnedFilters, appFilters] = _.partition( + lastKnownDoc.state?.filters, + esFilters.isFilterPinned + ); + const lastDocWithoutPinned = pinnedFilters?.length + ? { + ...lastKnownDoc, + state: { + ...lastKnownDoc.state, + filters: appFilters, + }, + } + : lastKnownDoc; + + const doc = { + ...lastDocWithoutPinned, + id: saveProps.newCopyOnSave ? undefined : lastKnownDoc.id, + title: saveProps.newTitle, + }; + + const newlyCreated: boolean = saveProps.newCopyOnSave || !lastKnownDoc?.id; + docStorage + .save(doc) + .then(({ id }) => { + // Prevents unnecessary network request and disables save button + const newDoc = { ...doc, id }; + setState(s => ({ + ...s, + isSaveModalVisible: false, + persistedDoc: newDoc, + lastKnownDoc: newDoc, + })); + if (docId !== id || saveProps.returnToOrigin) { + redirectTo(id, saveProps.returnToOrigin, newlyCreated); + } + }) + .catch(e => { + // eslint-disable-next-line no-console + console.dir(e); + trackUiEvent('save_failed'); + core.notifications.toasts.addDanger( + i18n.translate('xpack.lens.app.docSavingError', { + defaultMessage: 'Error saving document', + }) + ); + setState(s => ({ ...s, isSaveModalVisible: false })); + }); + }; + const onError = useCallback( (e: { message: string }) => core.notifications.toasts.addDanger({ @@ -192,13 +251,6 @@ export function App({ const { TopNavMenu } = navigation.ui; - const confirmButton = addToDashboardMode ? ( - - ) : null; - return ( { + if (isSaveable && lastKnownDoc) { + runSave({ + newTitle: lastKnownDoc.title, + newCopyOnSave: false, + isTitleDuplicateConfirmed: false, + returnToOrigin: true, + }); + } + }, + testId: 'lnsApp_saveAndReturnButton', + disableButton: !isSaveable, + }, + ] + : []), { - label: i18n.translate('xpack.lens.app.save', { - defaultMessage: 'Save', - }), + label: + lastKnownDoc?.id && !!originatingApp + ? i18n.translate('xpack.lens.app.saveAs', { + defaultMessage: 'Save as', + }) + : i18n.translate('xpack.lens.app.save', { + defaultMessage: 'Save', + }), + emphasize: !originatingApp || !lastKnownDoc?.id, run: () => { if (isSaveable && lastKnownDoc) { setState(s => ({ ...s, isSaveModalVisible: true })); @@ -336,63 +417,18 @@ export function App({ )} {lastKnownDoc && state.isSaveModalVisible && ( - { - const [pinnedFilters, appFilters] = _.partition( - lastKnownDoc.state?.filters, - esFilters.isFilterPinned - ); - const lastDocWithoutPinned = pinnedFilters?.length - ? { - ...lastKnownDoc, - state: { - ...lastKnownDoc.state, - filters: appFilters, - }, - } - : lastKnownDoc; - - const doc = { - ...lastDocWithoutPinned, - id: props.newCopyOnSave ? undefined : lastKnownDoc.id, - title: props.newTitle, - }; - - docStorage - .save(doc) - .then(({ id }) => { - // Prevents unnecessary network request and disables save button - const newDoc = { ...doc, id }; - setState(s => ({ - ...s, - isSaveModalVisible: false, - persistedDoc: newDoc, - lastKnownDoc: newDoc, - })); - if (docId !== id) { - redirectTo(id); - } - }) - .catch(e => { - // eslint-disable-next-line no-console - console.dir(e); - trackUiEvent('save_failed'); - core.notifications.toasts.addDanger( - i18n.translate('xpack.lens.app.docSavingError', { - defaultMessage: 'Error saving document', - }) - ); - setState(s => ({ ...s, isSaveModalVisible: false })); - }); - }} + runSave(props)} onClose={() => setState(s => ({ ...s, isSaveModalVisible: false }))} - title={lastKnownDoc.title || ''} - showCopyOnSave={!!lastKnownDoc.id && !addToDashboardMode} + documentInfo={{ + id: lastKnownDoc.id, + title: lastKnownDoc.title || '', + }} objectType={i18n.translate('xpack.lens.app.saveModalType', { defaultMessage: 'Lens visualization', })} - showDescription={false} - confirmButtonLabel={confirmButton} + data-test-subj="lnsApp_saveModalOrigin" /> )} diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index f295f88a58e5f..74bc5821aa713 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -11,8 +11,8 @@ import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom import { render, unmountComponentAtNode } from 'react-dom'; import rison from 'rison-node'; -import { DashboardConstants } from '../../../../../src/plugins/dashboard/public'; -import { Storage } from '../../../../../src/plugins/kibana_utils/public'; +import { parse } from 'query-string'; +import { Storage, removeQueryParam } from '../../../../../src/plugins/kibana_utils/public'; import { LensReportManager, setReportManager, trackUiEvent } from '../lens_ui_telemetry'; @@ -52,33 +52,48 @@ export async function mountApp( }; const redirectTo = ( routeProps: RouteComponentProps<{ id?: string }>, - addToDashboardMode: boolean, - id?: string + originatingApp: string, + id?: string, + returnToOrigin?: boolean, + newlyCreated?: boolean ) => { + if (!!originatingApp && !returnToOrigin) { + removeQueryParam(routeProps.history, 'embeddableOriginatingApp'); + } + if (!id) { routeProps.history.push('/lens'); - } else if (!addToDashboardMode) { + } else if (!originatingApp) { routeProps.history.push(`/lens/edit/${id}`); - } else if (addToDashboardMode && id) { + } else if (!!originatingApp && id && returnToOrigin) { routeProps.history.push(`/lens/edit/${id}`); - const lastDashboardLink = coreStart.chrome.navLinks.get('kibana:dashboard'); - if (!lastDashboardLink || !lastDashboardLink.url) { - throw new Error('Cannot get last dashboard url'); + const originatingAppLink = coreStart.chrome.navLinks.get(originatingApp); + if (!originatingAppLink || !originatingAppLink.url) { + throw new Error('Cannot get originating app url'); + } + + // TODO: Remove this and use application.redirectTo after https://github.com/elastic/kibana/pull/63443 + if (originatingApp === 'kibana:dashboard') { + const addLensId = newlyCreated ? id : ''; + const urlVars = getUrlVars(originatingAppLink.url); + updateUrlTime(urlVars); // we need to pass in timerange in query params directly + const dashboardUrl = addEmbeddableToDashboardUrl( + originatingAppLink.url, + addLensId, + urlVars + ); + window.history.pushState({}, '', dashboardUrl); + } else { + window.location.href = originatingAppLink.url; } - const urlVars = getUrlVars(lastDashboardLink.url); - updateUrlTime(urlVars); // we need to pass in timerange in query params directly - const dashboardUrl = addEmbeddableToDashboardUrl(lastDashboardLink.url, id, urlVars); - window.history.pushState({}, '', dashboardUrl); } }; const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => { trackUiEvent('loaded'); - const addToDashboardMode = - !!routeProps.location.search && - routeProps.location.search.includes( - DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM - ); + const urlParams = parse(routeProps.location.search) as Record; + const originatingApp = urlParams.embeddableOriginatingApp; + return ( redirectTo(routeProps, addToDashboardMode, id)} - addToDashboardMode={addToDashboardMode} + redirectTo={(id, returnToOrigin, newlyCreated) => + redirectTo(routeProps, originatingApp, id, returnToOrigin, newlyCreated) + } + originatingApp={originatingApp} /> ); }; diff --git a/x-pack/plugins/lens/public/helpers/url_helper.ts b/x-pack/plugins/lens/public/helpers/url_helper.ts index 0a97ba4b2edf7..2ffc381c4f62f 100644 --- a/x-pack/plugins/lens/public/helpers/url_helper.ts +++ b/x-pack/plugins/lens/public/helpers/url_helper.ts @@ -37,8 +37,10 @@ export function addEmbeddableToDashboardUrl(url: string, embeddableId: string, u keys.forEach(key => { dashboardParsedUrl.query[key] = urlVars[key]; }); - dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = 'lens'; - dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + if (embeddableId) { + dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_TYPE] = 'lens'; + dashboardParsedUrl.query[DashboardConstants.ADD_EMBEDDABLE_ID] = embeddableId; + } const query = stringify(dashboardParsedUrl.query); return `${dashboardParsedUrl.url}?${query}`; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 85b4c7f7eb032..b5b6ae7c64d32 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3969,7 +3969,6 @@ "visualize.listing.table.titleColumnName": "タイトル", "visualize.listing.table.typeColumnName": "タイプ", "visualize.pageHeading": "{chartName} {chartType} ビジュアライゼーション", - "visualize.saveDialog.saveAndAddToDashboardButtonLabel": "保存してダッシュボードに追加", "visualize.topNavMenu.openInspectorButtonAriaLabel": "ビジュアライゼーションのインスペクターを開く", "visualize.topNavMenu.openInspectorDisabledButtonTooltip": "このビジュアライゼーションはインスペクターをサポートしていません。", "visualize.topNavMenu.saveVisualization.failureNotificationText": "「{visTitle}」の保存中にエラーが発生しました", @@ -8363,7 +8362,6 @@ "xpack.lens.app.docSavingError": "ドキュメントの保存中にエラーが発生", "xpack.lens.app.indexPatternLoadingError": "インデックスパターンの読み込み中にエラーが発生", "xpack.lens.app.save": "保存", - "xpack.lens.app.saveAddToDashboard": "保存してダッシュボードに追加", "xpack.lens.app.saveModalType": "レンズビジュアライゼーション", "xpack.lens.app404": "404 Not Found", "xpack.lens.breadcrumbsCreate": "作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2f2b2b7f37481..1370295d1412f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3970,7 +3970,6 @@ "visualize.listing.table.titleColumnName": "标题", "visualize.listing.table.typeColumnName": "类型", "visualize.pageHeading": "{chartName} {chartType}可视化", - "visualize.saveDialog.saveAndAddToDashboardButtonLabel": "保存并添加到仪表板", "visualize.topNavMenu.openInspectorButtonAriaLabel": "打开检查器查看可视化", "visualize.topNavMenu.openInspectorDisabledButtonTooltip": "此可视化不支持任何检查器。", "visualize.topNavMenu.saveVisualization.failureNotificationText": "保存 “{visTitle}” 时出错", @@ -8369,7 +8368,6 @@ "xpack.lens.app.docSavingError": "保存文档时出错", "xpack.lens.app.indexPatternLoadingError": "加载索引模式时出错", "xpack.lens.app.save": "保存", - "xpack.lens.app.saveAddToDashboard": "保存并添加到仪表板", "xpack.lens.app.saveModalType": "Lens 可视化", "xpack.lens.app404": "404 找不到", "xpack.lens.breadcrumbsCreate": "创建", diff --git a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js index 19eebb3ba501c..c8ff3117506c3 100644 --- a/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js +++ b/x-pack/test/functional/apps/dashboard_mode/dashboard_empty_screen.js @@ -4,11 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ +import expect from '@kbn/expect'; + export default function({ getPageObjects, getService }) { const log = getService('log'); const testSubjects = getService('testSubjects'); const esArchiver = getService('esArchiver'); const dashboardVisualizations = getService('dashboardVisualizations'); + const dashboardPanelActions = getService('dashboardPanelActions'); const PageObjects = getPageObjects(['common', 'dashboard', 'visualize', 'lens']); describe('empty dashboard', function() { @@ -52,7 +55,7 @@ export default function({ getPageObjects, getService }) { operation: 'terms', field: 'ip', }); - await PageObjects.lens.save(title); + await PageObjects.lens.save(title, false, true); } it('adds Lens visualization to empty dashboard', async () => { @@ -64,5 +67,39 @@ export default function({ getPageObjects, getService }) { await PageObjects.dashboard.waitForRenderComplete(); await testSubjects.exists(`embeddablePanelHeading-${title}`); }); + + it('redirects via save and return button after edit', async () => { + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.lens.saveAndReturn(); + }); + + it('redirects via save as button after edit, renaming itself', async () => { + const newTitle = 'wowee, looks like I have a new title'; + const originalPanelCount = await PageObjects.dashboard.getPanelCount(); + await PageObjects.dashboard.waitForRenderComplete(); + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.lens.save(newTitle, false, true); + await PageObjects.dashboard.waitForRenderComplete(); + const newPanelCount = await PageObjects.dashboard.getPanelCount(); + expect(newPanelCount).to.eql(originalPanelCount); + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles.indexOf(newTitle)).to.not.be(-1); + }); + + it('redirects via save as button after edit, adding a new panel', async () => { + const newTitle = 'wowee, my title just got cooler'; + const originalPanelCount = await PageObjects.dashboard.getPanelCount(); + await PageObjects.dashboard.waitForRenderComplete(); + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickEdit(); + await PageObjects.lens.save(newTitle, true, true); + await PageObjects.dashboard.waitForRenderComplete(); + const newPanelCount = await PageObjects.dashboard.getPanelCount(); + expect(newPanelCount).to.eql(originalPanelCount + 1); + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles.indexOf(newTitle)).to.not.be(-1); + }); }); } diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 57b2847cc2e50..c4dcf63941cd5 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -133,9 +133,22 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont /** * Save the current Lens visualization. */ - async save(title: string) { + async save(title: string, saveAsNew?: boolean, redirectToOrigin?: boolean) { await testSubjects.click('lnsApp_saveButton'); await testSubjects.setValue('savedObjectTitle', title); + + const saveAsNewCheckboxExists = await testSubjects.exists('saveAsNewCheckbox'); + if (saveAsNewCheckboxExists) { + const state = saveAsNew ? 'check' : 'uncheck'; + await testSubjects.setEuiSwitch('saveAsNewCheckbox', state); + } + + const redirectToOriginCheckboxExists = await testSubjects.exists('returnToOriginModeSwitch'); + if (redirectToOriginCheckboxExists) { + const state = redirectToOrigin ? 'check' : 'uncheck'; + await testSubjects.setEuiSwitch('returnToOriginModeSwitch', state); + } + await testSubjects.click('confirmSaveSavedObjectButton'); retry.waitForWithTimeout('Save modal to disappear', 1000, () => testSubjects @@ -145,6 +158,10 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont ); }, + async saveAndReturn() { + await testSubjects.click('lnsApp_saveAndReturnButton'); + }, + getTitle() { return testSubjects.getVisibleText('lns_ChartTitle'); }, From bf7ace3109e34b314a031baa548177b8918fb4a9 Mon Sep 17 00:00:00 2001 From: gchaps <33642766+gchaps@users.noreply.github.com> Date: Tue, 5 May 2020 14:39:09 -0700 Subject: [PATCH 42/72] [DOCS] Fix indentation in code blocks in Timelion (#65343) --- docs/visualize/timelion.asciidoc | 166 +++++++++++++++++++++---------- 1 file changed, 115 insertions(+), 51 deletions(-) diff --git a/docs/visualize/timelion.asciidoc b/docs/visualize/timelion.asciidoc index a7520227977bc..852c3e1ecdeca 100644 --- a/docs/visualize/timelion.asciidoc +++ b/docs/visualize/timelion.asciidoc @@ -50,10 +50,10 @@ To compare the two data sets, add another series with data from the previous hou .es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct'), - .es(offset=-1h, <1> - index=metricbeat-*, - timefield='@timestamp', - metric='avg:system.cpu.user.pct') +.es(offset=-1h, <1> + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') ---------------------------------- <1> `offset` offsets the data retrieval by a date expression. In this example, `-1h` offsets the data back by one hour. @@ -119,11 +119,11 @@ To differentiate between the current hour data and the last hour data, change th metric='avg:system.cpu.user.pct') .label('last hour') .lines(fill=1,width=0.5), <1> - .es(index=metricbeat-*, - timefield='@timestamp', - metric='avg:system.cpu.user.pct') - .label('current hour') - .title('CPU usage over time') +.es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('current hour') + .title('CPU usage over time') ---------------------------------- <1> `.lines()` changes the appearance of the chart lines. In this example, `.lines(fill=1,width=0.5)` sets the fill level to `1`, and the border width to `0.5`. @@ -169,7 +169,20 @@ Change the position and style of the legend: [source,text] ---------------------------------- -.es(offset=-1h,index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('last hour').lines(fill=1,width=0.5).color(gray), .es(index=metricbeat-*, timefield='@timestamp', metric='avg:system.cpu.user.pct').label('current hour').title('CPU usage over time').color(#1E90FF).legend(columns=2, position=nw) <1> +.es(offset=-1h, + index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('last hour') + .lines(fill=1,width=0.5) + .color(gray), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='avg:system.cpu.user.pct') + .label('current hour') + .title('CPU usage over time') + .color(#1E90FF) + .legend(columns=2, position=nw) <1> ---------------------------------- <1> `.legend()` sets the position and style of the legend. In this example, `.legend(columns=2, position=nw)` places the legend in the north west position of the visualization with two columns. @@ -192,7 +205,9 @@ To start tracking the inbound and outbound network traffic, enter the following [source,text] ---------------------------------- -.es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.in.bytes) +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.in.bytes) ---------------------------------- [role="screenshot"] @@ -207,7 +222,10 @@ Change how the data is displayed so that you can easily monitor the inbound traf [source,text] ---------------------------------- -.es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.in.bytes).derivative() <1> +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.in.bytes) + .derivative() <1> ---------------------------------- <1> `.derivative` plots the change in values over time. @@ -220,7 +238,15 @@ Add a similar calculation for outbound traffic: [source,text] ---------------------------------- -.es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.in.bytes).derivative(), .es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.out.bytes).derivative().multiply(-1) <1> +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.in.bytes) + .derivative(), +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.out.bytes) + .derivative() + .multiply(-1) <1> ---------------------------------- <1> `.multiply()` multiplies the data series by a number, the result of a data series, or a list of data series. For this example, `.multiply(-1)` converts the outbound network traffic to a negative value since the outbound network traffic is leaving your machine. @@ -237,7 +263,17 @@ To make the visualization easier to analyze, change the data metric from bytes t [source,text] ---------------------------------- -.es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.in.bytes).derivative().divide(1048576), .es(index=metricbeat*, timefield=@timestamp, metric=max:system.network.out.bytes).derivative().multiply(-1).divide(1048576) <1> +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.in.bytes) + .derivative() + .divide(1048576), +.es(index=metricbeat*, + timefield=@timestamp, + metric=max:system.network.out.bytes) + .derivative() + .multiply(-1) + .divide(1048576) <1> ---------------------------------- <1> `.divide()` accepts the same input as `.multiply()`, then divides the data series by the defined divisor. @@ -271,8 +307,8 @@ Customize and format the visualization using functions: .divide(1048576) .lines(fill=2, width=1) <3> .color(blue) <4> - .label("Outbound traffic") - .legend(columns=2, position=nw) <5> + .label("Outbound traffic") + .legend(columns=2, position=nw) <5> ---------------------------------- <1> `.label()` adds custom labels to the visualization. @@ -309,7 +345,9 @@ To chart the maximum value of `system.memory.actual.used.bytes`, enter the follo [source,text] ---------------------------------- -.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes') +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') ---------------------------------- [role="screenshot"] @@ -338,17 +376,17 @@ To track the amount of memory used, create two thresholds: null) .label('warning') .color('#FFCC11'), - .es(index=metricbeat-*, - timefield='@timestamp', - metric='max:system.memory.actual.used.bytes') - .if(gt, - 11375000000, - .es(index=metricbeat-*, - timefield='@timestamp', - metric='max:system.memory.actual.used.bytes'), - null) - .label('severe') - .color('red') +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, + 11375000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('severe') + .color('red') ---------------------------------- <1> Timelion conditional logic for the _greater than_ operator. In this example, the warning threshold is 11.3GB (`11300000000`), and the severe threshold is 11.375GB (`11375000000`). If the threshold values are too high or low for your machine, adjust the values accordingly. @@ -366,7 +404,33 @@ To determine the trend, create a new data series: [source,text] ---------------------------------- -.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').if(gt,11300000000,.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'),null).label('warning').color('#FFCC11'), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').if(gt,11375000000,.es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'),null).label('severe').color('red'), .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes').mvavg(10) <1> +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt,11300000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null) + .label('warning') + .color('#FFCC11'), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt,11375000000, + .es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes'), + null). + label('severe') + .color('red'), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .mvavg(10) <1> ---------------------------------- <1> `mvavg()` calculates the moving average over a specified period of time. In this example, `.mvavg(10)` creates a moving average with a window of 10 data points. @@ -396,30 +460,30 @@ Customize and format the visualization using functions: .es(index=metricbeat-*, timefield='@timestamp', metric='max:system.memory.actual.used.bytes'), - null) - .label('warning') - .color('#FFCC11') <3> - .lines(width=5), <4> - .es(index=metricbeat-*, - timefield='@timestamp', - metric='max:system.memory.actual.used.bytes') - .if(gt, - 11375000000, - .es(index=metricbeat-*, - timefield='@timestamp', - metric='max:system.memory.actual.used.bytes'), - null) - .label('severe') - .color('red') - .lines(width=5), + null) + .label('warning') + .color('#FFCC11') <3> + .lines(width=5), <4> +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .if(gt, + 11375000000, .es(index=metricbeat-*, timefield='@timestamp', - metric='max:system.memory.actual.used.bytes') - .mvavg(10) - .label('mvavg') - .lines(width=2) - .color(#5E5E5E) - .legend(columns=4, position=nw) <5> + metric='max:system.memory.actual.used.bytes'), + null) + .label('severe') + .color('red') + .lines(width=5), +.es(index=metricbeat-*, + timefield='@timestamp', + metric='max:system.memory.actual.used.bytes') + .mvavg(10) + .label('mvavg') + .lines(width=2) + .color(#5E5E5E) + .legend(columns=4, position=nw) <5> ---------------------------------- <1> `.label()` adds custom labels to the visualization. From 509ea6a91ce1ce0ab32fe416576c2c8192517c25 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Tue, 5 May 2020 14:43:15 -0700 Subject: [PATCH 43/72] Updated README for alerting API (#65219) * Updated README for alerting API * Fixed due to comments --- x-pack/plugins/alerting/README.md | 33 +++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/alerting/README.md b/x-pack/plugins/alerting/README.md index 62c2caed669af..d15b5f4ce45cf 100644 --- a/x-pack/plugins/alerting/README.md +++ b/x-pack/plugins/alerting/README.md @@ -87,6 +87,7 @@ The following table describes the properties of the `options` object. |id|Unique identifier for the alert type. For convention purposes, ids starting with `.` are reserved for built in alert types. We recommend using a convention like `.mySpecialAlert` for your alert types to avoid conflicting with another plugin.|string| |name|A user-friendly name for the alert type. These will be displayed in dropdowns when choosing alert types.|string| |actionGroups|An explicit list of groups the alert type may schedule actions for, each specifying the ActionGroup's unique ID and human readable name. Alert `actions` validation will use this configuartion to ensure groups are valid. We highly encourage using `kbn-i18n` to translate the names of actionGroup when registering the AlertType. |Array<{id:string, name:string}>| +|defaultActionGroupId|Default ID value for the group of the alert type.|string| |actionVariables|An explicit list of action variables the alert type makes available via context and state in action parameter templates, and a short human readable description. Alert UI will use this to display prompts for the users for these variables, in action parameter editors. We highly encourage using `kbn-i18n` to translate the descriptions. |{ context: Array<{name:string, description:string}, state: Array<{name:string, description:string}>| |validate.params|When developing an alert type, you can choose to accept a series of parameters. You may also have the parameters validated before they are passed to the `executor` function or created as an alert saved object. In order to do this, provide a `@kbn/config-schema` schema that we will use to validate the `params` attribute.|@kbn/config-schema| |executor|This is where the code of the alert type lives. This is a function to be called when executing an alert on an interval basis. For full details, see executor section below.|Function| @@ -102,6 +103,7 @@ This is the primary function for an alert type. Whenever the alert needs to exec |services.callCluster(path, opts)|Use this to do Elasticsearch queries on the cluster Kibana connects to. This function is the same as any other `callCluster` in Kibana but in the context of the user who created the alert when security is enabled.| |services.savedObjectsClient|This is an instance of the saved objects client. This provides the ability to do CRUD on any saved objects within the same space the alert lives in.

The scope of the saved objects client is tied to the user who created the alert (only when security isenabled).| |services.getScopedCallCluster|This function scopes an instance of CallCluster by returning a `callCluster(path, opts)` function that runs in the context of the user who created the alert when security is enabled. This must only be called with instances of CallCluster provided by core.| +|services.alertInstanceFactory(id)|This [alert instance factory](#alert-instance-factory) creates instances of alerts and must be used in order to execute actions. The id you give to the alert instance factory is a unique identifier to the alert instance.| |services.log(tags, [data], [timestamp])|Use this to create server logs. (This is the same function as server.log)| |startedAt|The date and time the alert type started execution.| |previousStartedAt|The previous date and time the alert type started a successful execution.| @@ -117,7 +119,7 @@ This is the primary function for an alert type. Whenever the alert needs to exec ### The `actionVariables` property -This property should contain the **flattened** names of the state and context variables available when an executor calls `alertInstance.scheduleActions(groupName, context)`. These names are meant to be used in prompters in the alerting user interface, are used as text values for display, and can be inserted into to an action parameter text entry field via UI gesture (eg, clicking a menu item from a menu built with these names). They should be flattened, so if a state or context variable is an object with properties, these should be listed with the "parent" property/properties in the name, separated by a `.` (period). +This property should contain the **flattened** names of the state and context variables available when an executor calls `alertInstance.scheduleActions(actionGroup, context)`. These names are meant to be used in prompters in the alerting user interface, are used as text values for display, and can be inserted into to an action parameter text entry field via UI gesture (eg, clicking a menu item from a menu built with these names). They should be flattened, so if a state or context variable is an object with properties, these should be listed with the "parent" property/properties in the name, separated by a `.` (period). For example, if the `context` has one variable `foo` which is an object that has one property `bar`, and there are no `state` variables, the `actionVariables` value would be in the following shape: @@ -145,6 +147,17 @@ server.newPlatform.setup.plugins.alerting.registerType({ threshold: schema.number({ min: 0, max: 1 }), }), }, + actionGroups: [ + { + id: 'default', + name: 'Default', + }, + { + id: 'warning', + name: 'Warning', + }, + ], + defaultActionGroupId: 'default', actionVariables: { context: [ { name: 'server', description: 'the server' }, @@ -184,7 +197,7 @@ server.newPlatform.setup.plugins.alerting.registerType({ cpuUsage: currentCpuUsage, }); - // 'default' refers to a group of actions to be scheduled for execution, see 'actions' in create alert section + // 'default' refers to the id of a group of actions to be scheduled for execution, see 'actions' in create alert section alertInstance.scheduleActions('default', { server, hasCpuUsageIncreased: currentCpuUsage > previousCpuUsage, @@ -213,6 +226,13 @@ server.newPlatform.setup.plugins.alerting.registerType({ threshold: schema.number({ min: 0, max: 1 }), }), }, + actionGroups: [ + { + id: 'default', + name: 'Default', + }, + ], + defaultActionGroupId: 'default', actionVariables: { context: [ { name: 'server', description: 'the server' }, @@ -253,7 +273,7 @@ server.newPlatform.setup.plugins.alerting.registerType({ cpuUsage: currentCpuUsage, }); - // 'default' refers to a group of actions to be scheduled for execution, see 'actions' in create alert section + // 'default' refers to the id of a group of actions to be scheduled for execution, see 'actions' in create alert section alertInstance.scheduleActions('default', { server, hasCpuUsageIncreased: currentCpuUsage > previousCpuUsage, @@ -472,7 +492,7 @@ This factory returns an instance of `AlertInstance`. The alert instance class ha |Method|Description| |---|---| |getState()|Get the current state of the alert instance.| -|scheduleActions(actionGroup, context)|Called to schedule the execution of actions. The actionGroup relates to the group of alert `actions` to execute and the context will be used for templating purposes. This should only be called once per alert instance.| +|scheduleActions(actionGroup, context)|Called to schedule the execution of actions. The actionGroup is a string `id` that relates to the group of alert `actions` to execute and the context will be used for templating purposes. This should only be called once per alert instance.| |replaceState(state)|Used to replace the current state of the alert instance. This doesn't work like react, the entire state must be provided. Use this feature as you see fit. The state that is set will persist between alert type executions whenever you re-create an alert instance with the same id. The instance state will be erased when `scheduleActions` isn't called during an execution.| ## Templating actions @@ -489,6 +509,8 @@ When an alert instance executes, the first argument is the `group` of actions to - `spaceId` - the id of the space the alert exists in - `tags` - the tags set in the alert +The templating engine is [mustache]. General definition for the [mustache variable] is a double-brace {{}}. All variables are HTML-escaped by default and if there is a requirement to render unescaped HTML, it should be applied the triple mustache: `{{{name}}}`. Also, can be used `&` to unescape a variable. + ## Examples The following code would be within an alert type. As you can see `cpuUsage ` will replace the state of the alert instance and `server` is the context for the alert instance to execute. The difference between the two is `cpuUsage ` will be accessible at the next execution. @@ -537,3 +559,6 @@ The templating system will take the alert and alert type as described above and ``` There are limitations that we are aware of using only templates, and we are gathering feedback and use cases for these. (for example passing an array of strings to an action). + +[mustache]: https://github.com/janl/mustache.js +[mustache variable]: https://github.com/janl/mustache.js#variables From ee270c7c3ff915017414e7bd0b18ea2c53a3cea0 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 5 May 2020 14:56:22 -0700 Subject: [PATCH 44/72] disallow external imports to src/core/utils (#64852) --- .eslintrc.js | 5 ++ .../kibana-plugin-core-public.assertnever.md | 24 +++++++ .../kibana-plugin-core-public.deepfreeze.md | 24 +++++++ .../kibana-plugin-core-public.freezable.md | 14 ++++ ...a-plugin-core-public.getflattenedobject.md | 30 +++++++++ ...kibana-plugin-core-public.isrelativeurl.md | 24 +++++++ .../core/public/kibana-plugin-core-public.md | 12 ++++ .../kibana-plugin-core-public.modifyurl.md | 31 +++++++++ ...gin-core-public.urlmeaningfulparts.auth.md | 11 ++++ ...gin-core-public.urlmeaningfulparts.hash.md | 11 ++++ ...core-public.urlmeaningfulparts.hostname.md | 11 ++++ ...a-plugin-core-public.urlmeaningfulparts.md | 27 ++++++++ ...core-public.urlmeaningfulparts.pathname.md | 11 ++++ ...gin-core-public.urlmeaningfulparts.port.md | 11 ++++ ...core-public.urlmeaningfulparts.protocol.md | 11 ++++ ...in-core-public.urlmeaningfulparts.query.md | 11 ++++ ...-core-public.urlmeaningfulparts.slashes.md | 11 ++++ .../kibana-plugin-core-server.assertnever.md | 24 +++++++ .../kibana-plugin-core-server.deepfreeze.md | 24 +++++++ .../kibana-plugin-core-server.freezable.md | 14 ++++ ...a-plugin-core-server.getflattenedobject.md | 30 +++++++++ ...kibana-plugin-core-server.isrelativeurl.md | 24 +++++++ .../core/server/kibana-plugin-core-server.md | 7 ++ .../kibana-plugin-core-server.modifyurl.md | 31 +++++++++ ...gin-core-server.urlmeaningfulparts.auth.md | 11 ++++ ...gin-core-server.urlmeaningfulparts.hash.md | 11 ++++ ...core-server.urlmeaningfulparts.hostname.md | 11 ++++ ...a-plugin-core-server.urlmeaningfulparts.md | 27 ++++++++ ...core-server.urlmeaningfulparts.pathname.md | 11 ++++ ...gin-core-server.urlmeaningfulparts.port.md | 11 ++++ ...core-server.urlmeaningfulparts.protocol.md | 11 ++++ ...in-core-server.urlmeaningfulparts.query.md | 11 ++++ ...-core-server.urlmeaningfulparts.slashes.md | 11 ++++ src/core/public/index.ts | 12 +++- src/core/public/public.api.md | 43 ++++++++++++ src/core/server/index.ts | 12 +++- src/core/server/server.api.md | 65 +++++++++++++++++++ src/core/utils/assert_never.ts | 8 ++- src/core/utils/deep_freeze.ts | 11 +++- src/core/utils/get_flattened_object.ts | 3 +- src/core/utils/url.ts | 9 +++ src/legacy/core_plugins/kibana/index.js | 4 +- .../{ => server}/ui_setting_defaults.js | 5 +- src/legacy/core_plugins/timelion/index.ts | 2 +- src/legacy/ui/public/url/kibana_parsed_url.ts | 2 +- .../shard_failure_description.tsx | 2 +- .../public/angular/angular_config.tsx | 2 +- .../notify/app_redirect/app_redirect.ts | 2 +- src/plugins/share/server/routes/goto.ts | 2 +- .../vis_type_timelion/server/plugin.ts | 2 +- x-pack/legacy/plugins/canvas/index.js | 2 +- x-pack/legacy/plugins/dashboard_mode/index.js | 2 +- x-pack/legacy/plugins/maps/index.js | 2 +- .../actions/server/lib/license_state.ts | 2 +- .../alerting/server/lib/license_state.ts | 2 +- x-pack/plugins/apm/public/plugin.ts | 2 +- x-pack/plugins/features/server/plugin.ts | 2 +- x-pack/plugins/graph/common/check_license.ts | 7 +- x-pack/plugins/graph/public/plugin.ts | 2 +- .../public/state_management/url_templates.ts | 2 +- x-pack/plugins/infra/public/plugin.ts | 2 +- .../plugins/ingest_manager/public/plugin.ts | 2 +- x-pack/plugins/monitoring/public/plugin.ts | 2 +- .../server/authentication/providers/base.ts | 2 +- x-pack/plugins/security/server/plugin.ts | 2 +- .../spaces/server/saved_objects/mappings.ts | 2 +- .../api_consumer_plugin/server/index.ts | 2 +- 67 files changed, 737 insertions(+), 36 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.assertnever.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.deepfreeze.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.freezable.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.modifyurl.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.assertnever.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.deepfreeze.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.freezable.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.modifyurl.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md rename src/legacy/core_plugins/kibana/{ => server}/ui_setting_defaults.js (99%) diff --git a/.eslintrc.js b/.eslintrc.js index 9e3ab7cef8002..52a83452bd00f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -193,6 +193,11 @@ module.exports = { { basePath: __dirname, zones: [ + { + target: ['(src|x-pack)/**/*', '!src/core/**/*'], + from: ['src/core/utils/**/*'], + errorMessage: `Plugins may only import from src/core/server and src/core/public.`, + }, { target: [ '(src|x-pack)/legacy/**/*', diff --git a/docs/development/core/public/kibana-plugin-core-public.assertnever.md b/docs/development/core/public/kibana-plugin-core-public.assertnever.md new file mode 100644 index 0000000000000..8fefd4450d49b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.assertnever.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [assertNever](./kibana-plugin-core-public.assertnever.md) + +## assertNever() function + +Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking + +Signature: + +```typescript +export declare function assertNever(x: never): never; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| x | never | | + +Returns: + +`never` + diff --git a/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md b/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md new file mode 100644 index 0000000000000..7c879b659a852 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.deepfreeze.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [deepFreeze](./kibana-plugin-core-public.deepfreeze.md) + +## deepFreeze() function + +Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively + +Signature: + +```typescript +export declare function deepFreeze(object: T): RecursiveReadonly; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| object | T | | + +Returns: + +`RecursiveReadonly` + diff --git a/docs/development/core/public/kibana-plugin-core-public.freezable.md b/docs/development/core/public/kibana-plugin-core-public.freezable.md new file mode 100644 index 0000000000000..fee87dde25c28 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.freezable.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [Freezable](./kibana-plugin-core-public.freezable.md) + +## Freezable type + + +Signature: + +```typescript +export declare type Freezable = { + [k: string]: any; +} | any[]; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md b/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md new file mode 100644 index 0000000000000..3ef9b6bf703eb --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.getflattenedobject.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [getFlattenedObject](./kibana-plugin-core-public.getflattenedobject.md) + +## getFlattenedObject() function + +Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. + +example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } + +Signature: + +```typescript +export declare function getFlattenedObject(rootValue: Record): { + [key: string]: any; +}; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| rootValue | Record<string, any> | | + +Returns: + +`{ + [key: string]: any; +}` + diff --git a/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md b/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md new file mode 100644 index 0000000000000..3c2ffa6340a97 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.isrelativeurl.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [isRelativeUrl](./kibana-plugin-core-public.isrelativeurl.md) + +## isRelativeUrl() function + +Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* + +Signature: + +```typescript +export declare function isRelativeUrl(candidatePath: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| candidatePath | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index adc87de2b9e7e..c24e4cf908b87 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -27,6 +27,16 @@ The plugin integrates with the core system via lifecycle events: `setup` | [AppNavLinkStatus](./kibana-plugin-core-public.appnavlinkstatus.md) | Status of the application's navLink. | | [AppStatus](./kibana-plugin-core-public.appstatus.md) | Accessibility status of an application. | +## Functions + +| Function | Description | +| --- | --- | +| [assertNever(x)](./kibana-plugin-core-public.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | +| [deepFreeze(object)](./kibana-plugin-core-public.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | +| [getFlattenedObject(rootValue)](./kibana-plugin-core-public.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | +| [isRelativeUrl(candidatePath)](./kibana-plugin-core-public.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | +| [modifyUrl(url, urlModifier)](./kibana-plugin-core-public.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | + ## Interfaces | Interface | Description | @@ -118,6 +128,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ToastOptions](./kibana-plugin-core-public.toastoptions.md) | Options available for [IToasts](./kibana-plugin-core-public.itoasts.md) APIs. | | [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsState](./kibana-plugin-core-public.uisettingsstate.md) | | +| [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-public.userprovidedvalues.md) | Describes the values explicitly set by user. | ## Type Aliases @@ -139,6 +150,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | | [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | +| [Freezable](./kibana-plugin-core-public.freezable.md) | | | [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) to represent the type of the context. | | [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md) | A function that accepts a context object and an optional number of additional arguments. Used for the generic types in [IContextContainer](./kibana-plugin-core-public.icontextcontainer.md) | | [HandlerParameters](./kibana-plugin-core-public.handlerparameters.md) | Extracts the types of the additional arguments of a [HandlerFunction](./kibana-plugin-core-public.handlerfunction.md), excluding the [HandlerContextType](./kibana-plugin-core-public.handlercontexttype.md). | diff --git a/docs/development/core/public/kibana-plugin-core-public.modifyurl.md b/docs/development/core/public/kibana-plugin-core-public.modifyurl.md new file mode 100644 index 0000000000000..b174f733a5c64 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.modifyurl.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [modifyUrl](./kibana-plugin-core-public.modifyurl.md) + +## modifyUrl() function + +Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. + +Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash + +Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints + +Signature: + +```typescript +export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| url | string | | +| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | + +Returns: + +`string` + +The modified and reformatted url + diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md new file mode 100644 index 0000000000000..238dd66885896 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.auth.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) + +## URLMeaningfulParts.auth property + +Signature: + +```typescript +auth?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md new file mode 100644 index 0000000000000..161e7dc7ebfae --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hash.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) + +## URLMeaningfulParts.hash property + +Signature: + +```typescript +hash?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md new file mode 100644 index 0000000000000..f1884718337b5 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.hostname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) + +## URLMeaningfulParts.hostname property + +Signature: + +```typescript +hostname?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md new file mode 100644 index 0000000000000..2816d4c7df541 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) + +## URLMeaningfulParts interface + +We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". + +Signature: + +```typescript +export interface URLMeaningfulParts +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [auth](./kibana-plugin-core-public.urlmeaningfulparts.auth.md) | string | null | | +| [hash](./kibana-plugin-core-public.urlmeaningfulparts.hash.md) | string | null | | +| [hostname](./kibana-plugin-core-public.urlmeaningfulparts.hostname.md) | string | null | | +| [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) | string | null | | +| [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) | string | null | | +| [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) | string | null | | +| [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) | ParsedQuery | | +| [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) | boolean | null | | + diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md new file mode 100644 index 0000000000000..5ad21f004481c --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.pathname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-public.urlmeaningfulparts.pathname.md) + +## URLMeaningfulParts.pathname property + +Signature: + +```typescript +pathname?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md new file mode 100644 index 0000000000000..2e70da2f17421 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.port.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [port](./kibana-plugin-core-public.urlmeaningfulparts.port.md) + +## URLMeaningfulParts.port property + +Signature: + +```typescript +port?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md new file mode 100644 index 0000000000000..cedc7f0b878e3 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.protocol.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-public.urlmeaningfulparts.protocol.md) + +## URLMeaningfulParts.protocol property + +Signature: + +```typescript +protocol?: string | null; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md new file mode 100644 index 0000000000000..a9541efe0882a --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.query.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [query](./kibana-plugin-core-public.urlmeaningfulparts.query.md) + +## URLMeaningfulParts.query property + +Signature: + +```typescript +query: ParsedQuery; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md new file mode 100644 index 0000000000000..cb28a25f9e162 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.urlmeaningfulparts.slashes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [URLMeaningfulParts](./kibana-plugin-core-public.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-public.urlmeaningfulparts.slashes.md) + +## URLMeaningfulParts.slashes property + +Signature: + +```typescript +slashes?: boolean | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.assertnever.md b/docs/development/core/server/kibana-plugin-core-server.assertnever.md new file mode 100644 index 0000000000000..c13c88df9b9bf --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.assertnever.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [assertNever](./kibana-plugin-core-server.assertnever.md) + +## assertNever() function + +Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking + +Signature: + +```typescript +export declare function assertNever(x: never): never; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| x | never | | + +Returns: + +`never` + diff --git a/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md b/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md new file mode 100644 index 0000000000000..946050bff0585 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.deepfreeze.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [deepFreeze](./kibana-plugin-core-server.deepfreeze.md) + +## deepFreeze() function + +Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively + +Signature: + +```typescript +export declare function deepFreeze(object: T): RecursiveReadonly; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| object | T | | + +Returns: + +`RecursiveReadonly` + diff --git a/docs/development/core/server/kibana-plugin-core-server.freezable.md b/docs/development/core/server/kibana-plugin-core-server.freezable.md new file mode 100644 index 0000000000000..32ba89e8370c1 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.freezable.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [Freezable](./kibana-plugin-core-server.freezable.md) + +## Freezable type + + +Signature: + +```typescript +export declare type Freezable = { + [k: string]: any; +} | any[]; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md b/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md new file mode 100644 index 0000000000000..2e7850ca579f6 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.getflattenedobject.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [getFlattenedObject](./kibana-plugin-core-server.getflattenedobject.md) + +## getFlattenedObject() function + +Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from `rootValue`. + +example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } + +Signature: + +```typescript +export declare function getFlattenedObject(rootValue: Record): { + [key: string]: any; +}; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| rootValue | Record<string, any> | | + +Returns: + +`{ + [key: string]: any; +}` + diff --git a/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md b/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md new file mode 100644 index 0000000000000..bff9eb05419be --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.isrelativeurl.md @@ -0,0 +1,24 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [isRelativeUrl](./kibana-plugin-core-server.isrelativeurl.md) + +## isRelativeUrl() function + +Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* + +Signature: + +```typescript +export declare function isRelativeUrl(candidatePath: string): boolean; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| candidatePath | string | | + +Returns: + +`boolean` + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index a91a5bec988b7..14e01fda3d287 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -41,8 +41,13 @@ The plugin integrates with the core system via lifecycle events: `setup` | Function | Description | | --- | --- | +| [assertNever(x)](./kibana-plugin-core-server.assertnever.md) | Can be used in switch statements to ensure we perform exhaustive checks, see https://www.typescriptlang.org/docs/handbook/advanced-types.html\#exhaustiveness-checking | +| [deepFreeze(object)](./kibana-plugin-core-server.deepfreeze.md) | Apply Object.freeze to a value recursively and convert the return type to Readonly variant recursively | | [exportSavedObjectsToStream({ types, objects, search, savedObjectsClient, exportSizeLimit, includeReferencesDeep, excludeExportDetails, namespace, })](./kibana-plugin-core-server.exportsavedobjectstostream.md) | Generates sorted saved object stream to be used for export. See the [options](./kibana-plugin-core-server.savedobjectsexportoptions.md) for more detailed information. | +| [getFlattenedObject(rootValue)](./kibana-plugin-core-server.getflattenedobject.md) | Flattens a deeply nested object to a map of dot-separated paths pointing to all primitive values \*\*and arrays\*\* from rootValue.example: getFlattenedObject({ a: { b: 1, c: \[2,3\] } }) // => { 'a.b': 1, 'a.c': \[2,3\] } | | [importSavedObjectsFromStream({ readStream, objectLimit, overwrite, savedObjectsClient, supportedTypes, namespace, })](./kibana-plugin-core-server.importsavedobjectsfromstream.md) | Import saved objects from given stream. See the [options](./kibana-plugin-core-server.savedobjectsimportoptions.md) for more detailed information. | +| [isRelativeUrl(candidatePath)](./kibana-plugin-core-server.isrelativeurl.md) | Determine if a url is relative. Any url including a protocol, hostname, or port is not considered relative. This means that absolute \*paths\* are considered to be relative \*urls\* | +| [modifyUrl(url, urlModifier)](./kibana-plugin-core-server.modifyurl.md) | Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url.Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hashWhy? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints | | [resolveSavedObjectsImportErrors({ readStream, objectLimit, retries, savedObjectsClient, supportedTypes, namespace, })](./kibana-plugin-core-server.resolvesavedobjectsimporterrors.md) | Resolve and return saved object import errors. See the [options](./kibana-plugin-core-server.savedobjectsresolveimporterrorsoptions.md) for more detailed informations. | ## Interfaces @@ -186,6 +191,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [UiSettingsParams](./kibana-plugin-core-server.uisettingsparams.md) | UiSettings parameters defined by the plugins. | | [UiSettingsServiceSetup](./kibana-plugin-core-server.uisettingsservicesetup.md) | | | [UiSettingsServiceStart](./kibana-plugin-core-server.uisettingsservicestart.md) | | +| [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) | We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". | | [UserProvidedValues](./kibana-plugin-core-server.userprovidedvalues.md) | Describes the values explicitly set by user. | | [UuidServiceSetup](./kibana-plugin-core-server.uuidservicesetup.md) | APIs to access the application's instance uuid. | @@ -212,6 +218,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ConfigPath](./kibana-plugin-core-server.configpath.md) | | | [DestructiveRouteMethod](./kibana-plugin-core-server.destructiveroutemethod.md) | Set of HTTP methods changing the state of the server. | | [ElasticsearchClientConfig](./kibana-plugin-core-server.elasticsearchclientconfig.md) | | +| [Freezable](./kibana-plugin-core-server.freezable.md) | | | [GetAuthHeaders](./kibana-plugin-core-server.getauthheaders.md) | Get headers to authenticate a user against Elasticsearch. | | [GetAuthState](./kibana-plugin-core-server.getauthstate.md) | Gets authentication state for a request. Returned by auth interceptor. | | [HandlerContextType](./kibana-plugin-core-server.handlercontexttype.md) | Extracts the type of the first argument of a [HandlerFunction](./kibana-plugin-core-server.handlerfunction.md) to represent the type of the context. | diff --git a/docs/development/core/server/kibana-plugin-core-server.modifyurl.md b/docs/development/core/server/kibana-plugin-core-server.modifyurl.md new file mode 100644 index 0000000000000..fc0bc354a3ca3 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.modifyurl.md @@ -0,0 +1,31 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [modifyUrl](./kibana-plugin-core-server.modifyurl.md) + +## modifyUrl() function + +Takes a URL and a function that takes the meaningful parts of the URL as a key-value object, modifies some or all of the parts, and returns the modified parts formatted again as a url. + +Url Parts sent: - protocol - slashes (does the url have the //) - auth - hostname (just the name of the host, no port or auth information) - port - pathname (the path after the hostname, no query or hash, starts with a slash if there was a path) - query (always an object, even when no query on original url) - hash + +Why? - The default url library in node produces several conflicting properties on the "parsed" output. Modifying any of these might lead to the modifications being ignored (depending on which property was modified) - It's not always clear whether to use path/pathname, host/hostname, so this tries to add helpful constraints + +Signature: + +```typescript +export declare function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| url | string | | +| urlModifier | (urlParts: URLMeaningfulParts) => Partial<URLMeaningfulParts> | void | | + +Returns: + +`string` + +The modified and reformatted url + diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md new file mode 100644 index 0000000000000..0422738669a70 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.auth.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) + +## URLMeaningfulParts.auth property + +Signature: + +```typescript +auth?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md new file mode 100644 index 0000000000000..13a3f4a9c95c8 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hash.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) + +## URLMeaningfulParts.hash property + +Signature: + +```typescript +hash?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md new file mode 100644 index 0000000000000..6631f6f6744c5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.hostname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) + +## URLMeaningfulParts.hostname property + +Signature: + +```typescript +hostname?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md new file mode 100644 index 0000000000000..257f7b4b634ab --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.md @@ -0,0 +1,27 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) + +## URLMeaningfulParts interface + +We define our own typings because the current version of @types/node declares properties to be optional "hostname?: string". Although, parse call returns "hostname: null \| string". + +Signature: + +```typescript +export interface URLMeaningfulParts +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [auth](./kibana-plugin-core-server.urlmeaningfulparts.auth.md) | string | null | | +| [hash](./kibana-plugin-core-server.urlmeaningfulparts.hash.md) | string | null | | +| [hostname](./kibana-plugin-core-server.urlmeaningfulparts.hostname.md) | string | null | | +| [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) | string | null | | +| [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) | string | null | | +| [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) | string | null | | +| [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) | ParsedQuery | | +| [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) | boolean | null | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md new file mode 100644 index 0000000000000..8fee8c8e146ca --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.pathname.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [pathname](./kibana-plugin-core-server.urlmeaningfulparts.pathname.md) + +## URLMeaningfulParts.pathname property + +Signature: + +```typescript +pathname?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md new file mode 100644 index 0000000000000..dcf3517d92ba2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.port.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [port](./kibana-plugin-core-server.urlmeaningfulparts.port.md) + +## URLMeaningfulParts.port property + +Signature: + +```typescript +port?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md new file mode 100644 index 0000000000000..914dcd4e8a8a5 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.protocol.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [protocol](./kibana-plugin-core-server.urlmeaningfulparts.protocol.md) + +## URLMeaningfulParts.protocol property + +Signature: + +```typescript +protocol?: string | null; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md new file mode 100644 index 0000000000000..358adcfd3d180 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.query.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [query](./kibana-plugin-core-server.urlmeaningfulparts.query.md) + +## URLMeaningfulParts.query property + +Signature: + +```typescript +query: ParsedQuery; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md new file mode 100644 index 0000000000000..d5b598167f2f2 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.urlmeaningfulparts.slashes.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [URLMeaningfulParts](./kibana-plugin-core-server.urlmeaningfulparts.md) > [slashes](./kibana-plugin-core-server.urlmeaningfulparts.slashes.md) + +## URLMeaningfulParts.slashes property + +Signature: + +```typescript +slashes?: boolean | null; +``` diff --git a/src/core/public/index.ts b/src/core/public/index.ts index b4f64125a03ef..c30996b83c946 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -77,7 +77,17 @@ import { } from './context'; export { CoreContext, CoreSystem } from './core_system'; -export { RecursiveReadonly, DEFAULT_APP_CATEGORIES } from '../utils'; +export { + RecursiveReadonly, + DEFAULT_APP_CATEGORIES, + getFlattenedObject, + URLMeaningfulParts, + modifyUrl, + isRelativeUrl, + Freezable, + deepFreeze, + assertNever, +} from '../utils'; export { AppCategory, UiSettingsParams, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index af06b207889c2..c9fad5952bc7a 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -16,6 +16,7 @@ import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { MaybePromise } from '@kbn/utility-types'; import { Observable } from 'rxjs'; +import { ParsedQuery } from 'query-string'; import { PublicUiSettingsParams as PublicUiSettingsParams_2 } from 'src/core/server/types'; import React from 'react'; import * as Rx from 'rxjs'; @@ -174,6 +175,9 @@ export type AppUpdatableFields = Pick Partial | undefined; +// @public +export function assertNever(x: never): never; + // @public export interface Capabilities { [key: string]: Record>; @@ -434,6 +438,9 @@ export class CoreSystem { stop(): void; } +// @public +export function deepFreeze(object: T): RecursiveReadonly; + // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ analyze: { @@ -584,6 +591,16 @@ export interface FatalErrorsSetup { // @public export type FatalErrorsStart = FatalErrorsSetup; +// @public (undocumented) +export type Freezable = { + [k: string]: any; +} | any[]; + +// @public +export function getFlattenedObject(rootValue: Record): { + [key: string]: any; +}; + // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -795,6 +812,9 @@ export interface ImageValidation { }; } +// @public +export function isRelativeUrl(candidatePath: string): boolean; + // @public export type IToasts = Pick; @@ -857,6 +877,9 @@ export interface LegacyNavLink { url: string; } +// @public +export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; + // @public export type MountPoint = (element: T) => UnmountCallback; @@ -1356,6 +1379,26 @@ export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'sel // @public export type UnmountCallback = () => void; +// @public +export interface URLMeaningfulParts { + // (undocumented) + auth?: string | null; + // (undocumented) + hash?: string | null; + // (undocumented) + hostname?: string | null; + // (undocumented) + pathname?: string | null; + // (undocumented) + port?: string | null; + // (undocumented) + protocol?: string | null; + // (undocumented) + query: ParsedQuery; + // (undocumented) + slashes?: boolean | null; +} + // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 86192245bd2d1..cf999875b18f8 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -288,7 +288,17 @@ export { MetricsServiceSetup, } from './metrics'; -export { RecursiveReadonly } from '../utils'; +export { + RecursiveReadonly, + DEFAULT_APP_CATEGORIES, + getFlattenedObject, + URLMeaningfulParts, + modifyUrl, + isRelativeUrl, + Freezable, + deepFreeze, + assertNever, +} from '../utils'; export { SavedObject, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index e8b77a8570291..54b7a2ada69ad 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -103,6 +103,7 @@ import { NodesInfoParams } from 'elasticsearch'; import { NodesStatsParams } from 'elasticsearch'; import { ObjectType } from '@kbn/config-schema'; import { Observable } from 'rxjs'; +import { ParsedQuery } from 'query-string'; import { PeerCertificate } from 'tls'; import { PingParams } from 'elasticsearch'; import { PutScriptParams } from 'elasticsearch'; @@ -388,6 +389,9 @@ export interface APICaller { (endpoint: string, clientParams?: Record, options?: CallAPIOptions): Promise; } +// @public +export function assertNever(x: never): never; + // @public (undocumented) export interface AssistanceAPIResponse { // (undocumented) @@ -691,6 +695,31 @@ export interface CustomHttpResponseOptions(object: T): RecursiveReadonly; + +// @internal (undocumented) +export const DEFAULT_APP_CATEGORIES: Readonly<{ + analyze: { + label: string; + order: number; + }; + observability: { + label: string; + euiIconType: string; + order: number; + }; + security: { + label: string; + order: number; + euiIconType: string; + }; + management: { + label: string; + euiIconType: string; + }; +}>; + // @public (undocumented) export interface DeprecationAPIClientParams extends GenericParams { // (undocumented) @@ -838,6 +867,11 @@ export interface FakeRequest { headers: Headers; } +// @public (undocumented) +export type Freezable = { + [k: string]: any; +} | any[]; + // @public export type GetAuthHeaders = (request: KibanaRequest | LegacyRequest) => AuthHeaders | undefined; @@ -847,6 +881,11 @@ export type GetAuthState = (request: KibanaRequest | LegacyRequest) state: T; }; +// @public +export function getFlattenedObject(rootValue: Record): { + [key: string]: any; +}; + // @public export type HandlerContextType> = T extends HandlerFunction ? U : never; @@ -1034,6 +1073,9 @@ export type ISavedObjectTypeRegistry = Omit; +// @public +export function isRelativeUrl(candidatePath: string): boolean; + // @public export interface IUiSettingsClient { get: (key: string) => Promise; @@ -1289,6 +1331,9 @@ export type MIGRATION_ASSISTANCE_INDEX_ACTION = 'upgrade' | 'reindex'; // @public (undocumented) export type MIGRATION_DEPRECATION_LEVEL = 'none' | 'info' | 'warning' | 'critical'; +// @public +export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulParts) => Partial | void): string; + // @public export type MutatingOperationRefreshSetting = boolean | 'wait_for'; @@ -2447,6 +2492,26 @@ export interface UiSettingsServiceStart { // @public export type UiSettingsType = 'undefined' | 'json' | 'markdown' | 'number' | 'select' | 'boolean' | 'string' | 'array' | 'image'; +// @public +export interface URLMeaningfulParts { + // (undocumented) + auth?: string | null; + // (undocumented) + hash?: string | null; + // (undocumented) + hostname?: string | null; + // (undocumented) + pathname?: string | null; + // (undocumented) + port?: string | null; + // (undocumented) + protocol?: string | null; + // (undocumented) + query: ParsedQuery; + // (undocumented) + slashes?: boolean | null; +} + // @public export interface UserProvidedValues { // (undocumented) diff --git a/src/core/utils/assert_never.ts b/src/core/utils/assert_never.ts index 8e47f07a02a87..c713b373493c5 100644 --- a/src/core/utils/assert_never.ts +++ b/src/core/utils/assert_never.ts @@ -17,8 +17,12 @@ * under the License. */ -// Can be used in switch statements to ensure we perform exhaustive checks, see -// https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking +/** + * Can be used in switch statements to ensure we perform exhaustive checks, see + * https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking + * + * @public + */ export function assertNever(x: never): never { throw new Error(`Unexpected object: ${x}`); } diff --git a/src/core/utils/deep_freeze.ts b/src/core/utils/deep_freeze.ts index 8c3f8f2258b61..b0f283c60d0fc 100644 --- a/src/core/utils/deep_freeze.ts +++ b/src/core/utils/deep_freeze.ts @@ -17,8 +17,6 @@ * under the License. */ -type Freezable = { [k: string]: any } | any[]; - // if we define this inside RecursiveReadonly TypeScript complains // eslint-disable-next-line @typescript-eslint/no-empty-interface interface RecursiveReadonlyArray extends Array> {} @@ -32,6 +30,15 @@ export type RecursiveReadonly = T extends (...args: any[]) => any ? Readonly<{ [K in keyof T]: RecursiveReadonly }> : T; +/** @public */ +export type Freezable = { [k: string]: any } | any[]; + +/** + * Apply Object.freeze to a value recursively and convert the return type to + * Readonly variant recursively + * + * @public + */ export function deepFreeze(object: T) { // for any properties that reference an object, makes sure that object is // recursively frozen as well diff --git a/src/core/utils/get_flattened_object.ts b/src/core/utils/get_flattened_object.ts index ce03793284236..25ca0c7c83e26 100644 --- a/src/core/utils/get_flattened_object.ts +++ b/src/core/utils/get_flattened_object.ts @@ -30,8 +30,7 @@ function shouldReadKeys(value: unknown): value is Record { * getFlattenedObject({ a: { b: 1, c: [2,3] } }) * // => { 'a.b': 1, 'a.c': [2,3] } * - * @param {Object} rootValue - * @returns {Object} + * @public */ export function getFlattenedObject(rootValue: Record) { if (!shouldReadKeys(rootValue)) { diff --git a/src/core/utils/url.ts b/src/core/utils/url.ts index c2bf80ce3f86f..910fc8eaa4381 100644 --- a/src/core/utils/url.ts +++ b/src/core/utils/url.ts @@ -23,6 +23,8 @@ import { format as formatUrl, parse as parseUrl, UrlObject } from 'url'; * We define our own typings because the current version of @types/node * declares properties to be optional "hostname?: string". * Although, parse call returns "hostname: null | string". + * + * @public */ export interface URLMeaningfulParts { auth?: string | null; @@ -63,6 +65,7 @@ export interface URLMeaningfulParts { * @param url The string url to parse. * @param urlModifier A function that will modify the parsed url, or return a new one. * @returns The modified and reformatted url + * @public */ export function modifyUrl( url: string, @@ -100,6 +103,12 @@ export function modifyUrl( } as UrlObject); } +/** + * Determine if a url is relative. Any url including a protocol, hostname, or + * port is not considered relative. This means that absolute *paths* are considered + * to be relative *urls* + * @public + */ export function isRelativeUrl(candidatePath: string) { // validate that `candidatePath` is not attempting a redirect to somewhere // outside of this Kibana install diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index 51577456135d1..e786890567740 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -24,11 +24,11 @@ import { promisify } from 'util'; import { importApi } from './server/routes/api/import'; import { exportApi } from './server/routes/api/export'; import mappings from './mappings.json'; -import { getUiSettingDefaults } from './ui_setting_defaults'; +import { getUiSettingDefaults } from './server/ui_setting_defaults'; import { registerCspCollector } from './server/lib/csp_usage_collector'; import { injectVars } from './inject_vars'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; import { kbnBaseUrl } from '../../../plugins/kibana_legacy/server'; const mkdirAsync = promisify(Fs.mkdir); diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js similarity index 99% rename from src/legacy/core_plugins/kibana/ui_setting_defaults.js rename to src/legacy/core_plugins/kibana/server/ui_setting_defaults.js index 85b1956f45333..64b7dfe22fd57 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js @@ -16,13 +16,14 @@ * specific language governing permissions and limitations * under the License. */ + import moment from 'moment-timezone'; import numeralLanguages from '@elastic/numeral/languages'; import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; -import { DEFAULT_QUERY_LANGUAGE } from '../../../plugins/data/common'; -import { isRelativeUrl } from '../../../core/utils'; +import { isRelativeUrl } from '../../../../core/server'; +import { DEFAULT_QUERY_LANGUAGE } from '../../../../plugins/data/common'; export function getUiSettingDefaults() { const weekdays = moment.weekdays().slice(); diff --git a/src/legacy/core_plugins/timelion/index.ts b/src/legacy/core_plugins/timelion/index.ts index 41a15dc4e0186..4fdf27d7cf655 100644 --- a/src/legacy/core_plugins/timelion/index.ts +++ b/src/legacy/core_plugins/timelion/index.ts @@ -21,7 +21,7 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; import { Legacy } from 'kibana'; import { LegacyPluginApi, LegacyPluginInitializer } from 'src/legacy/plugin_discovery/types'; -import { DEFAULT_APP_CATEGORIES } from '../../../core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../core/server'; const experimentalLabel = i18n.translate('timelion.uiSettings.experimentalLabel', { defaultMessage: 'experimental', diff --git a/src/legacy/ui/public/url/kibana_parsed_url.ts b/src/legacy/ui/public/url/kibana_parsed_url.ts index 93d2e17d6038f..22288160acc6d 100644 --- a/src/legacy/ui/public/url/kibana_parsed_url.ts +++ b/src/legacy/ui/public/url/kibana_parsed_url.ts @@ -19,7 +19,7 @@ import { parse } from 'url'; -import { modifyUrl } from '../../../../core/utils'; +import { modifyUrl } from '../../../../core/public'; import { prependPath } from './prepend_path'; interface Options { diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx index d440f09ca09dd..3606bfbaeb1f9 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_description.tsx @@ -19,7 +19,7 @@ import React from 'react'; import { EuiCodeBlock, EuiDescriptionList, EuiSpacer } from '@elastic/eui'; import { ShardFailure } from './shard_failure_types'; -import { getFlattenedObject } from '../../../../../core/utils'; +import { getFlattenedObject } from '../../../../../core/public'; import { ShardFailureDescriptionHeader } from './shard_failure_description_header'; /** diff --git a/src/plugins/kibana_legacy/public/angular/angular_config.tsx b/src/plugins/kibana_legacy/public/angular/angular_config.tsx index 295cf27688c80..a52546d68c4d8 100644 --- a/src/plugins/kibana_legacy/public/angular/angular_config.tsx +++ b/src/plugins/kibana_legacy/public/angular/angular_config.tsx @@ -36,7 +36,7 @@ import { ChromeBreadcrumb, EnvironmentMode, PackageInfo } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { CoreStart, LegacyCoreStart } from 'kibana/public'; -import { modifyUrl } from '../../../../core/utils'; +import { modifyUrl } from '../../../../core/public'; import { toMountPoint } from '../../../kibana_react/public'; import { isSystemApiRequest, UrlOverflowService } from '../utils'; import { formatAngularHttpError, isAngularHttpError } from '../notify/lib'; diff --git a/src/plugins/kibana_legacy/public/notify/app_redirect/app_redirect.ts b/src/plugins/kibana_legacy/public/notify/app_redirect/app_redirect.ts index e79ab4b2fbc6d..01321c60f5c87 100644 --- a/src/plugins/kibana_legacy/public/notify/app_redirect/app_redirect.ts +++ b/src/plugins/kibana_legacy/public/notify/app_redirect/app_redirect.ts @@ -18,7 +18,7 @@ */ import { ILocationService } from 'angular'; -import { modifyUrl } from '../../../../../core/utils'; +import { modifyUrl } from '../../../../../core/public'; import { ToastsStart } from '../../../../../core/public'; const APP_REDIRECT_MESSAGE_PARAM = 'app_redirect_message'; diff --git a/src/plugins/share/server/routes/goto.ts b/src/plugins/share/server/routes/goto.ts index 747af3b9e57df..0dbddd6552c36 100644 --- a/src/plugins/share/server/routes/goto.ts +++ b/src/plugins/share/server/routes/goto.ts @@ -23,7 +23,7 @@ import { schema } from '@kbn/config-schema'; import { shortUrlAssertValid } from './lib/short_url_assert_valid'; import { ShortUrlLookupService } from './lib/short_url_lookup'; import { getGotoPath } from '../../common/short_url_routes'; -import { modifyUrl } from '../../../../core/utils'; +import { modifyUrl } from '../../../../core/server'; export const createGotoRoute = ({ router, diff --git a/src/plugins/vis_type_timelion/server/plugin.ts b/src/plugins/vis_type_timelion/server/plugin.ts index 40e89008e7562..435ec9027eef2 100644 --- a/src/plugins/vis_type_timelion/server/plugin.ts +++ b/src/plugins/vis_type_timelion/server/plugin.ts @@ -25,7 +25,7 @@ import { PluginInitializerContext, RecursiveReadonly, } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/utils'; +import { deepFreeze } from '../../../../src/core/server'; import { configSchema } from '../config'; import loadFunctions from './lib/load_functions'; import { functionsRoute } from './routes/functions'; diff --git a/x-pack/legacy/plugins/canvas/index.js b/x-pack/legacy/plugins/canvas/index.js index 4c7825e5b58aa..d9ea54de2d8a8 100644 --- a/x-pack/legacy/plugins/canvas/index.js +++ b/x-pack/legacy/plugins/canvas/index.js @@ -5,7 +5,7 @@ */ import { resolve } from 'path'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; import { CANVAS_APP, CANVAS_TYPE, CUSTOM_ELEMENT_TYPE } from './common/lib'; export function canvas(kibana) { diff --git a/x-pack/legacy/plugins/dashboard_mode/index.js b/x-pack/legacy/plugins/dashboard_mode/index.js index ab90c6511de01..b3f6ad8dd5348 100644 --- a/x-pack/legacy/plugins/dashboard_mode/index.js +++ b/x-pack/legacy/plugins/dashboard_mode/index.js @@ -6,7 +6,7 @@ import { resolve } from 'path'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; import { CONFIG_DASHBOARD_ONLY_MODE_ROLES } from './common'; import { createDashboardModeRequestInterceptor } from './server'; diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js index a1186e04ee27a..82d9a7b8e1d8f 100644 --- a/x-pack/legacy/plugins/maps/index.js +++ b/x-pack/legacy/plugins/maps/index.js @@ -17,7 +17,7 @@ import { createMapPath, MAP_SAVED_OBJECT_TYPE, } from '../../../plugins/maps/common/constants'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; export function maps(kibana) { return new kibana.Plugin({ diff --git a/x-pack/plugins/actions/server/lib/license_state.ts b/x-pack/plugins/actions/server/lib/license_state.ts index ae7180c4658bc..914aada08bb2c 100644 --- a/x-pack/plugins/actions/server/lib/license_state.ts +++ b/x-pack/plugins/actions/server/lib/license_state.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { Observable, Subscription } from 'rxjs'; -import { assertNever } from '../../../../../src/core/utils'; +import { assertNever } from '../../../../../src/core/server'; import { ILicense } from '../../../licensing/common/types'; import { PLUGIN } from '../constants/plugin'; import { ActionType } from '../types'; diff --git a/x-pack/plugins/alerting/server/lib/license_state.ts b/x-pack/plugins/alerting/server/lib/license_state.ts index db60d64db5df4..211d7a75dc4fa 100644 --- a/x-pack/plugins/alerting/server/lib/license_state.ts +++ b/x-pack/plugins/alerting/server/lib/license_state.ts @@ -8,7 +8,7 @@ import Boom from 'boom'; import { i18n } from '@kbn/i18n'; import { Observable, Subscription } from 'rxjs'; import { ILicense } from '../../../../plugins/licensing/common/types'; -import { assertNever } from '../../../../../src/core/utils'; +import { assertNever } from '../../../../../src/core/server'; import { PLUGIN } from '../constants/plugin'; export interface AlertingLicenseInformation { diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index f13c8853d0582..6ac2ecaae2b72 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -12,7 +12,7 @@ import { Plugin, PluginInitializerContext } from '../../../../src/core/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { PluginSetupContract as AlertingPluginPublicSetup, diff --git a/x-pack/plugins/features/server/plugin.ts b/x-pack/plugins/features/server/plugin.ts index 83cc9e1eb7cc8..2405f05768a2f 100644 --- a/x-pack/plugins/features/server/plugin.ts +++ b/x-pack/plugins/features/server/plugin.ts @@ -11,7 +11,7 @@ import { RecursiveReadonly, } from '../../../../src/core/server'; import { Capabilities as UICapabilities } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/utils'; +import { deepFreeze } from '../../../../src/core/server'; import { XPackInfo } from '../../../legacy/plugins/xpack_main/server/lib/xpack_info'; import { PluginSetupContract as TimelionSetupContract } from '../../../../src/plugins/vis_type_timelion/server'; import { FeatureRegistry } from './feature_registry'; diff --git a/x-pack/plugins/graph/common/check_license.ts b/x-pack/plugins/graph/common/check_license.ts index f9a663f35ed47..38d6c272f2784 100644 --- a/x-pack/plugins/graph/common/check_license.ts +++ b/x-pack/plugins/graph/common/check_license.ts @@ -6,7 +6,12 @@ import { i18n } from '@kbn/i18n'; import { ILicense } from '../../licensing/common/types'; -import { assertNever } from '../../../../src/core/utils'; + +// Can be used in switch statements to ensure we perform exhaustive checks, see +// https://www.typescriptlang.org/docs/handbook/advanced-types.html#exhaustiveness-checking +export function assertNever(x: never): never { + throw new Error(`Unexpected object: ${x}`); +} export interface GraphLicenseInformation { showAppLink: boolean; diff --git a/x-pack/plugins/graph/public/plugin.ts b/x-pack/plugins/graph/public/plugin.ts index 5521de705b6ec..4593ad9ba2613 100644 --- a/x-pack/plugins/graph/public/plugin.ts +++ b/x-pack/plugins/graph/public/plugin.ts @@ -21,7 +21,7 @@ import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { ConfigSchema } from '../config'; export interface GraphPluginSetupDependencies { diff --git a/x-pack/plugins/graph/public/state_management/url_templates.ts b/x-pack/plugins/graph/public/state_management/url_templates.ts index a0fb9503421a4..1701fc244ab52 100644 --- a/x-pack/plugins/graph/public/state_management/url_templates.ts +++ b/x-pack/plugins/graph/public/state_management/url_templates.ts @@ -17,7 +17,7 @@ import { setDatasource, IndexpatternDatasource, requestDatasource } from './data import { outlinkEncoders } from '../helpers/outlink_encoders'; import { urlTemplatePlaceholder } from '../helpers/url_template'; import { matchesOne } from './helpers'; -import { modifyUrl } from '../../../../../src/core/utils'; +import { modifyUrl } from '../../../../../src/core/public'; const actionCreator = actionCreatorFactory('x-pack/graph/urlTemplates'); diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index d61ef7fc4a631..866acec5b6ffe 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -12,7 +12,7 @@ import { PluginInitializerContext, AppMountParameters, } from 'kibana/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { registerStartSingleton } from './legacy_singletons'; import { registerFeatures } from './register_feature'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; diff --git a/x-pack/plugins/ingest_manager/public/plugin.ts b/x-pack/plugins/ingest_manager/public/plugin.ts index 90d82cf609d10..2c6ed9d81744e 100644 --- a/x-pack/plugins/ingest_manager/public/plugin.ts +++ b/x-pack/plugins/ingest_manager/public/plugin.ts @@ -11,7 +11,7 @@ import { CoreStart, } from 'src/core/public'; import { i18n } from '@kbn/i18n'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { LicensingPluginSetup } from '../../licensing/public'; import { PLUGIN_ID } from '../common/constants'; diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index 63f0c46c14096..8e2fe2c869ea1 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -17,7 +17,7 @@ import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/utils'; +import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { MonitoringPluginDependencies, MonitoringConfig } from './types'; import { MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS, diff --git a/x-pack/plugins/security/server/authentication/providers/base.ts b/x-pack/plugins/security/server/authentication/providers/base.ts index 48a73586a6fed..d2d2e82951a3e 100644 --- a/x-pack/plugins/security/server/authentication/providers/base.ts +++ b/x-pack/plugins/security/server/authentication/providers/base.ts @@ -11,7 +11,7 @@ import { IClusterClient, Headers, } from '../../../../../../src/core/server'; -import { deepFreeze } from '../../../../../../src/core/utils'; +import { deepFreeze } from '../../../../../../src/core/server'; import { AuthenticatedUser } from '../../../common/model'; import { AuthenticationResult } from '../authentication_result'; import { DeauthenticationResult } from '../deauthentication_result'; diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index 97f5aea888dc7..77a2d716e6d87 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -13,7 +13,7 @@ import { Logger, PluginInitializerContext, } from '../../../../src/core/server'; -import { deepFreeze } from '../../../../src/core/utils'; +import { deepFreeze } from '../../../../src/core/server'; import { SpacesPluginSetup } from '../../spaces/server'; import { PluginSetupContract as FeaturesSetupContract } from '../../features/server'; import { LicensingPluginSetup } from '../../licensing/server'; diff --git a/x-pack/plugins/spaces/server/saved_objects/mappings.ts b/x-pack/plugins/spaces/server/saved_objects/mappings.ts index 00e1ab732a8a5..3afa7c389927c 100644 --- a/x-pack/plugins/spaces/server/saved_objects/mappings.ts +++ b/x-pack/plugins/spaces/server/saved_objects/mappings.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { deepFreeze } from '../../../../../src/core/utils'; +import { deepFreeze } from '../../../../../src/core/server'; export const SpacesSavedObjectMappings = deepFreeze({ properties: { diff --git a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts index 1a01cf8929c05..838a1d1c9461c 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/fixtures/api_consumer_plugin/server/index.ts @@ -5,7 +5,7 @@ */ import { CoreSetup, PluginInitializer } from '../../../../../../src/core/server'; -import { deepFreeze } from '../../../../../../src/core/utils'; +import { deepFreeze } from '../../../../../../src/core/server'; import { EncryptedSavedObjectsPluginSetup, EncryptedSavedObjectsPluginStart, From ecd16dcc7114d2c8445f0b5de524b016612e2a2e Mon Sep 17 00:00:00 2001 From: Andrew Goldstein Date: Tue, 5 May 2020 16:26:49 -0600 Subject: [PATCH 45/72] Drag between ANDs in timeline queries / add to timeline (#65228) ## Summary This enhancement: - Enables drag and drop between `AND`s in a timeline query to narrow or widen a search ![drag-between-ANDs](https://user-images.githubusercontent.com/4459398/81045705-f457cf00-8e73-11ea-9df0-231a30e1bbd9.gif) - Introduces a new `Add to timeline investigation` context menu action that automatically drags and drops any draggable to the timeline ![add-to-timeline](https://user-images.githubusercontent.com/4459398/81045745-08033580-8e74-11ea-9f3e-0e173f925aea.gif) - When dragging while the timeline is closed, the timeline drop target automatically opens (and closes), making it possible to directly add to an existing `AND` (in addition to the original behavior, which added an `OR`) ![drag-directly-to-group](https://user-images.githubusercontent.com/4459398/81045882-5e707400-8e74-11ea-8c18-91399546214c.gif) ### Desk testing Desk tested in: - Chrome `81.0.4044.129` - Firefox `75.0` - Safari `13.1` --- .../timeline_data_providers.spec.ts | 2 +- .../drag_drop_context_wrapper.tsx | 99 +- .../drag_and_drop/draggable_wrapper.tsx | 1 + .../draggable_wrapper_hover_content.tsx | 17 + .../components/drag_and_drop/helpers.test.ts | 95 -- .../components/drag_and_drop/helpers.ts | 113 +- .../components/drag_and_drop/translations.ts | 4 + .../public/components/flyout/button/index.tsx | 180 ++- .../__snapshots__/timeline.test.tsx.snap | 2 - .../__snapshots__/empty.test.tsx.snap | 4 +- .../__snapshots__/providers.test.tsx.snap | 1012 +++++++++-------- .../data_providers/data_providers.test.tsx | 27 - .../timeline/data_providers/empty.tsx | 6 +- .../timeline/data_providers/helpers.tsx | 334 ++++++ .../timeline/data_providers/index.tsx | 76 +- .../data_providers/provider_badge.tsx | 39 +- .../data_providers/provider_item_and.tsx | 95 -- .../provider_item_and_drag_drop.tsx | 136 --- .../data_providers/provider_item_badge.tsx | 33 +- .../data_providers/providers.test.tsx | 44 +- .../timeline/data_providers/providers.tsx | 334 +++--- .../timeline/data_providers/translations.ts | 2 +- .../header/__snapshots__/index.test.tsx.snap | 2 - .../components/timeline/header/index.test.tsx | 6 - .../components/timeline/header/index.tsx | 33 +- .../siem/public/components/timeline/index.tsx | 16 - .../components/timeline/timeline.test.tsx | 2 - .../public/components/timeline/timeline.tsx | 8 - .../plugins/siem/public/hooks/translations.ts | 6 + .../siem/public/hooks/use_add_to_timeline.tsx | 165 +++ .../public/hooks/use_providers_portal.tsx | 20 + 31 files changed, 1573 insertions(+), 1340 deletions(-) create mode 100644 x-pack/plugins/siem/public/components/timeline/data_providers/helpers.tsx delete mode 100644 x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and.tsx delete mode 100644 x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and_drag_drop.tsx create mode 100644 x-pack/plugins/siem/public/hooks/use_add_to_timeline.tsx create mode 100644 x-pack/plugins/siem/public/hooks/use_providers_portal.tsx diff --git a/x-pack/plugins/siem/cypress/integration/timeline_data_providers.spec.ts b/x-pack/plugins/siem/cypress/integration/timeline_data_providers.spec.ts index 4889d40ae7d39..08eb3df57c7a0 100644 --- a/x-pack/plugins/siem/cypress/integration/timeline_data_providers.spec.ts +++ b/x-pack/plugins/siem/cypress/integration/timeline_data_providers.spec.ts @@ -49,7 +49,7 @@ describe('timeline data providers', () => { .first() .invoke('text') .should(hostname => { - expect(dataProviderText).to.eq(`host.name: "${hostname}"`); + expect(dataProviderText).to.eq(`host.name: "${hostname}"AND`); }); }); }); diff --git a/x-pack/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx b/x-pack/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx index 248ae671550ef..8e6743ad8f92e 100644 --- a/x-pack/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx +++ b/x-pack/plugins/siem/public/components/drag_and_drop/drag_drop_context_wrapper.tsx @@ -12,9 +12,15 @@ import { Dispatch } from 'redux'; import { BeforeCapture } from './drag_drop_context'; import { BrowserFields } from '../../containers/source'; -import { dragAndDropModel, dragAndDropSelectors } from '../../store'; +import { dragAndDropModel, dragAndDropSelectors, timelineSelectors } from '../../store'; import { IdToDataProvider } from '../../store/drag_and_drop/model'; import { State } from '../../store/reducer'; +import { DataProvider } from '../timeline/data_providers/data_provider'; +import { reArrangeProviders } from '../timeline/data_providers/helpers'; +import { ACTIVE_TIMELINE_REDUX_ID } from '../top_n'; +import { ADDED_TO_TIMELINE_MESSAGE } from '../../hooks/translations'; +import { useAddToTimelineSensor } from '../../hooks/use_add_to_timeline'; +import { displaySuccessToast, useStateToaster } from '../toasters'; import { addFieldToTimelineColumns, @@ -23,8 +29,8 @@ import { IS_DRAGGING_CLASS_NAME, IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME, providerWasDroppedOnTimeline, - providerWasDroppedOnTimelineButton, draggableIsField, + userIsReArrangingProviders, } from './helpers'; // @ts-ignore @@ -37,58 +43,92 @@ interface Props { } interface OnDragEndHandlerParams { + activeTimelineDataProviders: DataProvider[]; browserFields: BrowserFields; dataProviders: IdToDataProvider; dispatch: Dispatch; + onAddedToTimeline: (fieldOrValue: string) => void; result: DropResult; } const onDragEndHandler = ({ + activeTimelineDataProviders, browserFields, dataProviders, dispatch, + onAddedToTimeline, result, }: OnDragEndHandlerParams) => { - if (providerWasDroppedOnTimeline(result)) { - addProviderToTimeline({ dataProviders, result, dispatch }); - } else if (providerWasDroppedOnTimelineButton(result)) { - addProviderToTimeline({ dataProviders, result, dispatch }); + if (userIsReArrangingProviders(result)) { + reArrangeProviders({ + dataProviders: activeTimelineDataProviders, + destination: result.destination, + dispatch, + source: result.source, + timelineId: ACTIVE_TIMELINE_REDUX_ID, + }); + } else if (providerWasDroppedOnTimeline(result)) { + addProviderToTimeline({ + activeTimelineDataProviders, + dataProviders, + dispatch, + onAddedToTimeline, + result, + timelineId: ACTIVE_TIMELINE_REDUX_ID, + }); } else if (fieldWasDroppedOnTimelineColumns(result)) { - addFieldToTimelineColumns({ browserFields, dispatch, result }); + addFieldToTimelineColumns({ + browserFields, + dispatch, + result, + timelineId: ACTIVE_TIMELINE_REDUX_ID, + }); } }; +const sensors = [useAddToTimelineSensor]; + /** * DragDropContextWrapperComponent handles all drag end events */ export const DragDropContextWrapperComponent = React.memo( - ({ browserFields, children, dataProviders, dispatch }) => { + ({ activeTimelineDataProviders, browserFields, children, dataProviders, dispatch }) => { + const [, dispatchToaster] = useStateToaster(); + const onAddedToTimeline = useCallback( + (fieldOrValue: string) => { + displaySuccessToast(ADDED_TO_TIMELINE_MESSAGE(fieldOrValue), dispatchToaster); + }, + [dispatchToaster] + ); + const onDragEnd = useCallback( (result: DropResult) => { - enableScrolling(); - - if (dataProviders != null) { - onDragEndHandler({ - browserFields, - result, - dataProviders, - dispatch, - }); - } - - if (!draggableIsField(result)) { + try { + enableScrolling(); + + if (dataProviders != null) { + onDragEndHandler({ + activeTimelineDataProviders, + browserFields, + dataProviders, + dispatch, + onAddedToTimeline, + result, + }); + } + } finally { document.body.classList.remove(IS_DRAGGING_CLASS_NAME); - } - if (draggableIsField(result)) { - document.body.classList.remove(IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME); + if (draggableIsField(result)) { + document.body.classList.remove(IS_TIMELINE_FIELD_DRAGGING_CLASS_NAME); + } } }, - [browserFields, dataProviders] + [dataProviders, activeTimelineDataProviders, browserFields] ); return ( // @ts-ignore - + {children} ); @@ -96,7 +136,8 @@ export const DragDropContextWrapperComponent = React.memo { return ( prevProps.children === nextProps.children && - prevProps.dataProviders === nextProps.dataProviders + prevProps.dataProviders === nextProps.dataProviders && + prevProps.activeTimelineDataProviders === nextProps.activeTimelineDataProviders ); // prevent re-renders when data providers are added or removed, but all other props are the same } ); @@ -104,11 +145,15 @@ export const DragDropContextWrapperComponent = React.memo { + const activeTimelineDataProviders = + timelineSelectors.getTimelineByIdSelector()(state, ACTIVE_TIMELINE_REDUX_ID)?.dataProviders ?? + emptyActiveTimelineDataProviders; const dataProviders = dragAndDropSelectors.dataProvidersSelector(state) ?? emptyDataProviders; - return { dataProviders }; + return { activeTimelineDataProviders, dataProviders }; }; const connector = connect(mapStateToProps); diff --git a/x-pack/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx index c7da5b5c58951..5676c8fe5c30b 100644 --- a/x-pack/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/plugins/siem/public/components/drag_and_drop/draggable_wrapper.tsx @@ -132,6 +132,7 @@ export const DraggableWrapper = React.memo( const hoverContent = useMemo( () => ( void; showTopN: boolean; @@ -26,12 +29,14 @@ interface Props { } const DraggableWrapperHoverContentComponent: React.FC = ({ + draggableId, field, onFilterAdded, showTopN, toggleTopN, value, }) => { + const startDragToTimeline = useAddToTimeline({ draggableId, fieldName: field }); const kibana = useKibana(); const { filterManager: timelineFilterManager } = useTimelineContext(); const filterManager = useMemo(() => kibana.services.data.query.filterManager, [ @@ -92,6 +97,18 @@ const DraggableWrapperHoverContentComponent: React.FC = ({ )} + {!showTopN && value != null && draggableId != null && ( + + + + )} + {({ browserFields }) => ( <> diff --git a/x-pack/plugins/siem/public/components/drag_and_drop/helpers.test.ts b/x-pack/plugins/siem/public/components/drag_and_drop/helpers.test.ts index 753fa5b54eade..333875feae4d1 100644 --- a/x-pack/plugins/siem/public/components/drag_and_drop/helpers.test.ts +++ b/x-pack/plugins/siem/public/components/drag_and_drop/helpers.test.ts @@ -28,7 +28,6 @@ import { getDroppableId, getFieldIdFromDraggable, getProviderIdFromDraggable, - getTimelineIdFromDestination, providerWasDroppedOnTimeline, reasonIsDrop, sourceIsContent, @@ -381,100 +380,6 @@ describe('helpers', () => { }); }); - describe('#getTimelineIdFromDestination', () => { - test('it returns returns the timeline id from the destination when it is a provider', () => { - expect( - getTimelineIdFromDestination({ - destination: { - droppableId: DROPPABLE_ID_TIMELINE_PROVIDERS, - index: 0, - }, - draggableId: getDraggableId('685260508808089'), - reason: 'DROP', - source: { - droppableId: getDroppableId('685260508808089'), - index: 0, - }, - type: 'DEFAULT', - mode: 'FLUID', - }) - ).toEqual('timeline'); - }); - - test('it returns returns the timeline id from the destination when the destination is timeline columns', () => { - expect( - getTimelineIdFromDestination({ - destination: { - droppableId: DROPPABLE_ID_TIMELINE_COLUMNS, - index: 0, - }, - draggableId: getDraggableFieldId({ contextId: 'test', fieldId: 'event.action' }), - reason: 'DROP', - source: { - droppableId: 'fake.source.droppable.id', - index: 0, - }, - type: 'DEFAULT', - mode: 'FLUID', - }) - ).toEqual('timeline-1'); - }); - - test('it returns returns the timeline id from the destination when it is a button', () => { - expect( - getTimelineIdFromDestination({ - destination: { - droppableId: `${droppableTimelineFlyoutButtonPrefix}timeline`, - index: 0, - }, - draggableId: getDraggableId('685260508808089'), - reason: 'DROP', - source: { - droppableId: getDroppableId('685260508808089'), - index: 0, - }, - type: 'DEFAULT', - mode: 'FLUID', - }) - ).toEqual('timeline'); - }); - - test('it returns returns an empty string when the destination is undefined', () => { - expect( - getTimelineIdFromDestination({ - destination: undefined, - draggableId: `${draggableIdPrefix}.timeline.timeline.dataProvider.685260508808089`, - reason: 'DROP', - source: { - droppableId: `${droppableIdPrefix}.timelineProviders.timeline`, - index: 0, - }, - type: 'DEFAULT', - mode: 'FLUID', - }) - ).toEqual(''); - }); - - test('it returns returns an empty string when the destination is not a timeline', () => { - expect( - getTimelineIdFromDestination({ - destination: { - droppableId: `${droppableIdPrefix}.somewhere.else`, - index: 0, - }, - draggableId: getDraggableId('685260508808089'), - reason: 'DROP', - source: { - droppableId: getDroppableId('685260508808089'), - index: 0, - }, - type: 'DEFAULT', - mode: 'FLUID', - }) - ).toEqual(''); - }); - }); - describe('#getProviderIdFromDraggable', () => { test('it returns the expected id', () => { const id = getProviderIdFromDraggable({ diff --git a/x-pack/plugins/siem/public/components/drag_and_drop/helpers.ts b/x-pack/plugins/siem/public/components/drag_and_drop/helpers.ts index cd3d7cc68d537..9b37387ce076b 100644 --- a/x-pack/plugins/siem/public/components/drag_and_drop/helpers.ts +++ b/x-pack/plugins/siem/public/components/drag_and_drop/helpers.ts @@ -10,12 +10,12 @@ import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; import { BrowserField, BrowserFields, getAllFieldsByName } from '../../containers/source'; +import { dragAndDropActions, timelineActions } from '../../store/actions'; import { IdToDataProvider } from '../../store/drag_and_drop/model'; import { ColumnHeaderOptions } from '../../store/timeline/model'; import { DEFAULT_COLUMN_MIN_WIDTH } from '../timeline/body/constants'; - import { DataProvider } from '../timeline/data_providers/data_provider'; -import { dragAndDropActions, timelineActions } from '../../store/actions'; +import { addContentToTimeline } from '../timeline/data_providers/helpers'; export const draggableIdPrefix = 'draggableId'; @@ -23,6 +23,8 @@ export const droppableIdPrefix = 'droppableId'; export const draggableContentPrefix = `${draggableIdPrefix}.content.`; +export const draggableTimelineProvidersPrefix = `${draggableIdPrefix}.timelineProviders.`; + export const draggableFieldPrefix = `${draggableIdPrefix}.field.`; export const droppableContentPrefix = `${droppableIdPrefix}.content.`; @@ -46,12 +48,43 @@ export const getDraggableFieldId = ({ fieldId: string; }): string => `${draggableFieldPrefix}${escapeContextId(contextId)}.${escapeFieldId(fieldId)}`; +export const getTimelineProviderDroppableId = ({ + groupIndex, + timelineId, +}: { + groupIndex: number; + timelineId: string; +}): string => `${droppableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}`; + +export const getTimelineProviderDraggableId = ({ + dataProviderId, + groupIndex, + timelineId, +}: { + dataProviderId: string; + groupIndex: number; + timelineId: string; +}): string => + `${draggableTimelineProvidersPrefix}${timelineId}.group.${groupIndex}.${dataProviderId}`; + export const getDroppableId = (visualizationPlaceholderId: string): string => `${droppableContentPrefix}${visualizationPlaceholderId}`; export const sourceIsContent = (result: DropResult): boolean => result.source.droppableId.startsWith(droppableContentPrefix); +export const sourceAndDestinationAreSameTimelineProviders = (result: DropResult): boolean => { + const regex = /^droppableId\.timelineProviders\.(\S+)\./; + const sourceMatches = result.source.droppableId.match(regex) ?? []; + const destinationMatches = result.destination?.droppableId.match(regex) ?? []; + + return ( + sourceMatches.length >= 2 && + destinationMatches.length >= 2 && + sourceMatches[1] === destinationMatches[1] + ); +}; + export const draggableIsContent = (result: DropResult | { draggableId: string }): boolean => result.draggableId.startsWith(draggableContentPrefix); @@ -72,14 +105,6 @@ export const destinationIsTimelineButton = (result: DropResult): boolean => result.destination != null && result.destination.droppableId.startsWith(droppableTimelineFlyoutButtonPrefix); -export const getTimelineIdFromDestination = (result: DropResult): string => - result.destination != null && - (destinationIsTimelineProviders(result) || - destinationIsTimelineButton(result) || - destinationIsTimelineColumns(result)) - ? result.destination.droppableId.substring(result.destination.droppableId.lastIndexOf('.') + 1) - : ''; - export const getProviderIdFromDraggable = (result: DropResult): string => result.draggableId.substring(result.draggableId.lastIndexOf('.') + 1); @@ -100,26 +125,22 @@ export const providerWasDroppedOnTimeline = (result: DropResult): boolean => sourceIsContent(result) && destinationIsTimelineProviders(result); +export const userIsReArrangingProviders = (result: DropResult): boolean => + reasonIsDrop(result) && sourceAndDestinationAreSameTimelineProviders(result); + export const fieldWasDroppedOnTimelineColumns = (result: DropResult): boolean => reasonIsDrop(result) && draggableIsField(result) && destinationIsTimelineColumns(result); -export const providerWasDroppedOnTimelineButton = (result: DropResult): boolean => - reasonIsDrop(result) && - draggableIsContent(result) && - sourceIsContent(result) && - destinationIsTimelineButton(result); - interface AddProviderToTimelineParams { + activeTimelineDataProviders: DataProvider[]; dataProviders: IdToDataProvider; - result: DropResult; dispatch: Dispatch; - addProvider?: ActionCreator<{ - id: string; - provider: DataProvider; - }>; noProviderFound?: ActionCreator<{ id: string; }>; + onAddedToTimeline: (fieldOrValue: string) => void; + result: DropResult; + timelineId: string; } interface AddFieldToTimelineColumnsParams { @@ -131,21 +152,30 @@ interface AddFieldToTimelineColumnsParams { browserFields: BrowserFields; dispatch: Dispatch; result: DropResult; + timelineId: string; } export const addProviderToTimeline = ({ + activeTimelineDataProviders, dataProviders, - result, dispatch, - addProvider = timelineActions.addProvider, + result, + timelineId, noProviderFound = dragAndDropActions.noProviderFound, + onAddedToTimeline, }: AddProviderToTimelineParams): void => { - const timeline = getTimelineIdFromDestination(result); const providerId = getProviderIdFromDraggable(result); - const provider = dataProviders[providerId]; - - if (provider) { - dispatch(addProvider({ id: timeline, provider })); + const providerToAdd = dataProviders[providerId]; + + if (providerToAdd) { + addContentToTimeline({ + dataProviders: activeTimelineDataProviders, + destination: result.destination, + dispatch, + onAddedToTimeline, + providerToAdd, + timelineId, + }); } else { dispatch(noProviderFound({ id: providerId })); } @@ -156,8 +186,8 @@ export const addFieldToTimelineColumns = ({ browserFields, dispatch, result, + timelineId, }: AddFieldToTimelineColumnsParams): void => { - const timeline = getTimelineIdFromDestination(result); const fieldId = getFieldIdFromDraggable(result); const allColumns = getAllFieldsByName(browserFields); const column = allColumns[fieldId]; @@ -175,7 +205,7 @@ export const addFieldToTimelineColumns = ({ aggregatable: column.aggregatable, width: DEFAULT_COLUMN_MIN_WIDTH, }, - id: timeline, + id: timelineId, index: result.destination != null ? result.destination.index : 0, }) ); @@ -188,34 +218,13 @@ export const addFieldToTimelineColumns = ({ id: fieldId, width: DEFAULT_COLUMN_MIN_WIDTH, }, - id: timeline, + id: timelineId, index: result.destination != null ? result.destination.index : 0, }) ); } }; -interface ShowTimelineParams { - result: DropResult; - show: boolean; - dispatch: Dispatch; - showTimeline?: ActionCreator<{ - id: string; - show: boolean; - }>; -} - -export const updateShowTimeline = ({ - result, - show, - dispatch, - showTimeline = timelineActions.showTimeline, -}: ShowTimelineParams): void => { - const timeline = getTimelineIdFromDestination(result); - - dispatch(showTimeline({ id: timeline, show })); -}; - /** * Prevents fields from being dragged or dropped to any area other than column * header drop zone in the timeline diff --git a/x-pack/plugins/siem/public/components/drag_and_drop/translations.ts b/x-pack/plugins/siem/public/components/drag_and_drop/translations.ts index 61d036635a250..cbcb34bd9f75e 100644 --- a/x-pack/plugins/siem/public/components/drag_and_drop/translations.ts +++ b/x-pack/plugins/siem/public/components/drag_and_drop/translations.ts @@ -6,6 +6,10 @@ import { i18n } from '@kbn/i18n'; +export const ADD_TO_TIMELINE = i18n.translate('xpack.siem.dragAndDrop.addToTimeline', { + defaultMessage: 'Add to timeline investigation', +}); + export const COPY_TO_CLIPBOARD = i18n.translate('xpack.siem.dragAndDrop.copyToClipboardTooltip', { defaultMessage: 'Copy to Clipboard', }); diff --git a/x-pack/plugins/siem/public/components/flyout/button/index.tsx b/x-pack/plugins/siem/public/components/flyout/button/index.tsx index 6ec5912872467..d0debbca4dec3 100644 --- a/x-pack/plugins/siem/public/components/flyout/button/index.tsx +++ b/x-pack/plugins/siem/public/components/flyout/button/index.tsx @@ -4,67 +4,48 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiNotificationBadge, EuiIcon, EuiButton } from '@elastic/eui'; +import { noop } from 'lodash/fp'; +import { EuiButton, EuiNotificationBadge, EuiPanel } from '@elastic/eui'; import { rgba } from 'polished'; -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { DroppableWrapper } from '../../drag_and_drop/droppable_wrapper'; -import { - droppableTimelineFlyoutButtonPrefix, - IS_DRAGGING_CLASS_NAME, -} from '../../drag_and_drop/helpers'; +import { WithSource } from '../../../containers/source'; +import { IS_DRAGGING_CLASS_NAME } from '../../drag_and_drop/helpers'; +import { DataProviders } from '../../timeline/data_providers'; import { DataProvider } from '../../timeline/data_providers/data_provider'; +import { flattenIntoAndGroups } from '../../timeline/data_providers/helpers'; import * as i18n from './translations'; -export const NOT_READY_TO_DROP_CLASS_NAME = 'not-ready-to-drop'; -export const READY_TO_DROP_CLASS_NAME = 'ready-to-drop'; +export const FLYOUT_BUTTON_CLASS_NAME = 'timeline-flyout-button'; + +export const getBadgeCount = (dataProviders: DataProvider[]): number => + flattenIntoAndGroups(dataProviders).reduce((total, group) => total + group.length, 0); + +const SHOW_HIDE_TRANSLATE_X = 497; // px const Container = styled.div` - overflow-x: auto; - overflow-y: hidden; padding-top: 8px; position: fixed; + right: 0px; top: 40%; - right: -51px; - z-index: ${({ theme }) => theme.eui.euiZLevel9}; - transform: rotate(-90deg); + transform: translateX(${SHOW_HIDE_TRANSLATE_X}px); user-select: none; + width: 500px; + z-index: ${({ theme }) => theme.eui.euiZLevel9}; - button { - border-radius: 4px 4px 0 0; - box-shadow: none; - height: 46px; - margin: 1px 0 1px 1px; - width: 136px; - } - - .euiButton:hover:not(:disabled) { + .${IS_DRAGGING_CLASS_NAME} & { transform: none; } - .euiButton--primary:enabled { - background: ${({ theme }) => theme.eui.euiColorEmptyShade}; - box-shadow: none; - } - - .euiButton--primary:enabled:hover, - .euiButton--primary:enabled:focus { - animation: none; - background: ${({ theme }) => theme.eui.euiColorEmptyShade}; + .${FLYOUT_BUTTON_CLASS_NAME} { + border-radius: 4px 4px 0 0; box-shadow: none; + height: 46px; } - .${IS_DRAGGING_CLASS_NAME} & .${NOT_READY_TO_DROP_CLASS_NAME} { - color: ${({ theme }) => theme.eui.euiColorSuccess}; - background: ${({ theme }) => rgba(theme.eui.euiColorSuccess, 0.1)} !important; - border: 1px solid ${({ theme }) => theme.eui.euiColorSuccess}; - border-bottom: none; - text-decoration: none; - } - - .${READY_TO_DROP_CLASS_NAME} { + .${IS_DRAGGING_CLASS_NAME} & .${FLYOUT_BUTTON_CLASS_NAME} { color: ${({ theme }) => theme.eui.euiColorSuccess}; background: ${({ theme }) => rgba(theme.eui.euiColorSuccess, 0.2)} !important; border: 1px solid ${({ theme }) => theme.eui.euiColorSuccess}; @@ -79,10 +60,21 @@ const BadgeButtonContainer = styled.div` align-items: flex-start; display: flex; flex-direction: row; + left: -87px; + position: absolute; + top: 34px; + transform: rotate(-90deg); `; BadgeButtonContainer.displayName = 'BadgeButtonContainer'; +const DataProvidersPanel = styled(EuiPanel)` + border-radius: 0; + padding: 0 4px 0 4px; + user-select: none; + z-index: ${({ theme }) => theme.eui.euiZLevel9}; +`; + interface FlyoutButtonProps { dataProviders: DataProvider[]; onOpen: () => void; @@ -91,57 +83,63 @@ interface FlyoutButtonProps { } export const FlyoutButton = React.memo( - ({ onOpen, show, dataProviders, timelineId }) => - show ? ( - - ( - - {!isDraggingOver ? ( - - {i18n.FLYOUT_BUTTON} - - ) : ( - - - - )} - - - {dataProviders.length} - - - )} - /> + ({ onOpen, show, dataProviders, timelineId }) => { + const badgeCount = useMemo(() => getBadgeCount(dataProviders), [dataProviders]); + + if (!show) { + return null; + } + + return ( + + + + {i18n.FLYOUT_BUTTON} + + + {badgeCount} + + + + + {({ browserFields }) => ( + + )} + + - ) : null, + ); + }, (prevProps, nextProps) => prevProps.show === nextProps.show && prevProps.dataProviders === nextProps.dataProviders && diff --git a/x-pack/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap b/x-pack/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap index a8ba787477797..3854fc6b985ac 100644 --- a/x-pack/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap +++ b/x-pack/plugins/siem/public/components/timeline/__snapshots__/timeline.test.tsx.snap @@ -722,8 +722,6 @@ exports[`Timeline rendering renders correctly against snapshot 1`] = ` "title": "filebeat-*,auditbeat-*,packetbeat-*", } } - onChangeDataProviderKqlQuery={[MockFunction]} - onChangeDroppableAndProvider={[MockFunction]} onDataProviderEdited={[MockFunction]} onDataProviderRemoved={[MockFunction]} onToggleDataProviderEnabled={[MockFunction]} diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/empty.test.tsx.snap b/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/empty.test.tsx.snap index 5b4405b8d3bc7..dac95c302af27 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/empty.test.tsx.snap +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/empty.test.tsx.snap @@ -14,7 +14,9 @@ exports[`Empty rendering renders correctly against snapshot 1`] = ` Drop anything - + highlighted diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/providers.test.tsx.snap b/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/providers.test.tsx.snap index b344381f99d4f..330306b00e7c1 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/providers.test.tsx.snap +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/__snapshots__/providers.test.tsx.snap @@ -1,514 +1,534 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Providers rendering renders correctly against snapshot 1`] = ` - - - + + + + + + + + + ( + + + + + + + + + + ) + + + + + + + + + + + + ( + + + + + + + + + + ) + + + + + + + + + + + + ( + + + + + + + + + + ) + + + + + + + + + + + + ( + + + + + + + + + + ) + + + + + + + + + + + + ( + + + + + + + + + + ) + + + + + + + + + + + + ( + + - - - - - - - - - - - + + + + + ) + + + + + + - - - - - - - - - - + + + + + ( + + + + - - - - - - - - - - + + + + + ) + + + + + + - - - - - - - - - - + + + + + ( + + + + + + + + + + ) + + + + + + - - - - - - - - - - + + + + + ( + + + + - - - - - - - - - - + + + + + ) + + + + + + - - - - - - - - - - + + + + + ( + + + + - - - - - - - - - - + + + + + ) + + + + + + - - - - - - - - - - + + + + + ( + + + + - - - - - - - - - - - - - - Drop here - - to build an - - OR - - query - - - + + + + + + ) + + + +
`; diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/data_providers.test.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/data_providers.test.tsx index a88062d9093d7..b77d37e8e31ab 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/data_providers.test.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/data_providers.test.tsx @@ -26,8 +26,6 @@ describe('DataProviders', () => { browserFields={{}} id="foo" dataProviders={mockDataProviders} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -47,29 +45,6 @@ describe('DataProviders', () => { browserFields={{}} id="foo" dataProviders={dataProviders} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} - onDataProviderEdited={jest.fn()} - onDataProviderRemoved={jest.fn()} - onToggleDataProviderEnabled={jest.fn()} - onToggleDataProviderExcluded={jest.fn()} - show={true} - /> - - ); - - dropMessage.forEach(word => expect(wrapper.text()).toContain(word)); - }); - - test('it should STILL render a placeholder given a non-empty collection of data providers', () => { - const wrapper = mount( - - { browserFields={{}} id="foo" dataProviders={mockDataProviders} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/empty.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/empty.tsx index 60c868f780ff3..1c225eba20b4f 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/empty.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/empty.tsx @@ -12,6 +12,8 @@ import { AndOrBadge } from '../../and_or_badge'; import * as i18n from './translations'; +export const HIGHLIGHTED_DROP_TARGET_CLASS_NAME = 'highlighted-drop-target'; + const Text = styled(EuiText)` overflow: hidden; margin: 5px 0 5px 0; @@ -88,7 +90,9 @@ export const Empty = React.memo(({ showSmallMsg = false }) => ( {i18n.DROP_ANYTHING} - {i18n.HIGHLIGHTED} + + {i18n.HIGHLIGHTED} + diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/helpers.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/helpers.tsx new file mode 100644 index 0000000000000..8b10ee550096f --- /dev/null +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/helpers.tsx @@ -0,0 +1,334 @@ +/* + * 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 { omit } from 'lodash/fp'; +import { DraggableLocation } from 'react-beautiful-dnd'; +import { Dispatch } from 'redux'; + +import { updateProviders } from '../../../store/timeline/actions'; + +import { DataProvider, DataProvidersAnd } from './data_provider'; + +export const omitAnd = (provider: DataProvider): DataProvidersAnd => omit('and', provider); + +export const reorder = ( + group: DataProvidersAnd[], + startIndex: number, + endIndex: number +): DataProvidersAnd[] => { + const groupClone = [...group]; + const [removed] = groupClone.splice(startIndex, 1); // ⚠️ mutation + groupClone.splice(endIndex, 0, removed); // ⚠️ mutation + + return groupClone; +}; + +export const move = ({ + destinationGroup, + moveProviderFromSourceIndex, + moveProviderToDestinationIndex, + sourceGroup, +}: { + destinationGroup: DataProvidersAnd[]; + moveProviderFromSourceIndex: number; + moveProviderToDestinationIndex: number; + sourceGroup: DataProvidersAnd[]; +}): { + updatedDestinationGroup: DataProvidersAnd[]; + updatedSourceGroup: DataProvidersAnd[]; +} => { + const sourceClone = [...sourceGroup]; + const destinationClone = [...destinationGroup]; + + const [removed] = sourceClone.splice(moveProviderFromSourceIndex, 1); // ⚠️ mutation + destinationClone.splice(moveProviderToDestinationIndex, 0, removed); // ⚠️ mutation + + const deDuplicatedDestinationGroup = destinationClone.filter((provider, i) => + provider.id === removed.id && i !== moveProviderToDestinationIndex ? false : true + ); + + return { + updatedDestinationGroup: deDuplicatedDestinationGroup, + updatedSourceGroup: sourceClone, + }; +}; + +export const isValidDestination = ( + destination: DraggableLocation | undefined +): destination is DraggableLocation => destination != null; + +export const sourceAndDestinationAreSameDroppable = ({ + destination, + source, +}: { + destination: DraggableLocation; + source: DraggableLocation; +}): boolean => source.droppableId === destination.droppableId; + +export const flattenIntoAndGroups = (dataProviders: DataProvider[]): DataProvidersAnd[][] => + dataProviders.reduce( + (acc, provider) => [...acc, [omitAnd(provider), ...provider.and]], + [] + ); + +export const reArrangeProvidersInSameGroup = ({ + dataProviderGroups, + destination, + dispatch, + source, + timelineId, +}: { + dataProviderGroups: DataProvidersAnd[][]; + destination: DraggableLocation; + dispatch: Dispatch; + source: DraggableLocation; + timelineId: string; +}) => { + const groupIndex = getGroupIndexFromDroppableId(source.droppableId); + + if ( + indexIsValid({ + index: groupIndex, + dataProviderGroups, + }) + ) { + const reorderedGroup = reorder(dataProviderGroups[groupIndex], source.index, destination.index); + + const updatedGroups = dataProviderGroups.reduce( + (acc, group, i) => [...acc, i === groupIndex ? [...reorderedGroup] : [...group]], + [] + ); + + dispatch( + updateProviders({ + id: timelineId, + providers: unFlattenGroups(updatedGroups.filter(g => g.length)), + }) + ); + } +}; + +export const getGroupIndexFromDroppableId = (droppableId: string): number => + Number(droppableId.substring(droppableId.lastIndexOf('.') + 1)); + +export const indexIsValid = ({ + index, + dataProviderGroups, +}: { + index: number; + dataProviderGroups: DataProvidersAnd[][]; +}): boolean => index >= 0 && index < dataProviderGroups.length; + +export const convertDataProviderAnd = (dataProvidersAnd: DataProvidersAnd): DataProvider => ({ + ...dataProvidersAnd, + and: [], +}); + +export const unFlattenGroups = (groups: DataProvidersAnd[][]): DataProvider[] => + groups.reduce((acc, group) => [...acc, { ...group[0], and: group.slice(1) }], []); + +export const moveProvidersBetweenGroups = ({ + dataProviderGroups, + destination, + dispatch, + source, + timelineId, +}: { + dataProviderGroups: DataProvidersAnd[][]; + destination: DraggableLocation; + dispatch: Dispatch; + source: DraggableLocation; + timelineId: string; +}) => { + const sourceGroupIndex = getGroupIndexFromDroppableId(source.droppableId); + const destinationGroupIndex = getGroupIndexFromDroppableId(destination.droppableId); + + if ( + indexIsValid({ + index: sourceGroupIndex, + dataProviderGroups, + }) && + indexIsValid({ + index: destinationGroupIndex, + dataProviderGroups, + }) + ) { + const sourceGroup = dataProviderGroups[sourceGroupIndex]; + const destinationGroup = dataProviderGroups[destinationGroupIndex]; + const moveProviderFromSourceIndex = source.index; + const moveProviderToDestinationIndex = destination.index; + + const { updatedDestinationGroup, updatedSourceGroup } = move({ + destinationGroup, + moveProviderFromSourceIndex, + moveProviderToDestinationIndex, + sourceGroup, + }); + + const updatedGroups = dataProviderGroups.reduce( + (acc, group, i) => [ + ...acc, + i === sourceGroupIndex + ? [...updatedSourceGroup] + : i === destinationGroupIndex + ? [...updatedDestinationGroup] + : [...group], + ], + [] + ); + + dispatch( + updateProviders({ + id: timelineId, + providers: unFlattenGroups(updatedGroups.filter(g => g.length)), + }) + ); + } +}; + +export const addProviderToEmptyTimeline = ({ + dispatch, + onAddedToTimeline, + providerToAdd, + timelineId, +}: { + dispatch: Dispatch; + onAddedToTimeline: (fieldOrValue: string) => void; + providerToAdd: DataProvider; + timelineId: string; +}) => { + dispatch( + updateProviders({ + id: timelineId, + providers: [providerToAdd], + }) + ); + + onAddedToTimeline(providerToAdd.name); +}; + +/** Rendered as a constant drop target for creating a new OR group */ +export const EMPTY_GROUP: DataProvidersAnd[][] = [[]]; + +export const reArrangeProviders = ({ + dataProviders, + destination, + dispatch, + source, + timelineId, +}: { + dataProviders: DataProvider[]; + destination: DraggableLocation | undefined; + dispatch: Dispatch; + source: DraggableLocation; + timelineId: string; +}) => { + if (!isValidDestination(destination)) { + return; + } + + const dataProviderGroups = [...flattenIntoAndGroups(dataProviders), ...EMPTY_GROUP]; + + if (sourceAndDestinationAreSameDroppable({ source, destination })) { + reArrangeProvidersInSameGroup({ + dataProviderGroups, + destination, + dispatch, + source, + timelineId, + }); + } else { + moveProvidersBetweenGroups({ + dataProviderGroups, + destination, + dispatch, + source, + timelineId, + }); + } +}; + +export const addProviderToGroup = ({ + dataProviders, + destination, + dispatch, + onAddedToTimeline, + providerToAdd, + timelineId, +}: { + dataProviders: DataProvider[]; + destination: DraggableLocation | undefined; + dispatch: Dispatch; + onAddedToTimeline: (fieldOrValue: string) => void; + providerToAdd: DataProvider; + timelineId: string; +}) => { + const dataProviderGroups = [...flattenIntoAndGroups(dataProviders), ...EMPTY_GROUP]; + + if (!isValidDestination(destination)) { + return; + } + + const destinationGroupIndex = getGroupIndexFromDroppableId(destination.droppableId); + if ( + indexIsValid({ + index: destinationGroupIndex, + dataProviderGroups, + }) + ) { + const destinationGroup = dataProviderGroups[destinationGroupIndex]; + const destinationClone = [...destinationGroup]; + destinationClone.splice(destination.index, 0, omitAnd(providerToAdd)); // ⚠️ mutation + const deDuplicatedGroup = destinationClone.filter((provider, i) => + provider.id === providerToAdd.id && i !== destination.index ? false : true + ); + + const updatedGroups = dataProviderGroups.reduce( + (acc, group, i) => [ + ...acc, + i === destinationGroupIndex ? [...deDuplicatedGroup] : [...group], + ], + [] + ); + + dispatch( + updateProviders({ + id: timelineId, + providers: unFlattenGroups(updatedGroups.filter(g => g.length)), + }) + ); + onAddedToTimeline(providerToAdd.name); + } +}; + +export const addContentToTimeline = ({ + dataProviders, + destination, + dispatch, + onAddedToTimeline, + providerToAdd, + timelineId, +}: { + dataProviders: DataProvider[]; + destination: DraggableLocation | undefined; + dispatch: Dispatch; + onAddedToTimeline: (fieldOrValue: string) => void; + providerToAdd: DataProvider; + timelineId: string; +}) => { + if (dataProviders.length === 0) { + addProviderToEmptyTimeline({ dispatch, onAddedToTimeline, providerToAdd, timelineId }); + } else { + addProviderToGroup({ + dataProviders, + destination, + dispatch, + onAddedToTimeline, + providerToAdd, + timelineId, + }); + } +}; diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/index.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/index.tsx index f369b961807af..caead394db051 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/index.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/index.tsx @@ -15,8 +15,6 @@ import { IS_DRAGGING_CLASS_NAME, } from '../../drag_and_drop/helpers'; import { - OnChangeDataProviderKqlQuery, - OnChangeDroppableAndProvider, OnDataProviderEdited, OnDataProviderRemoved, OnToggleDataProviderEnabled, @@ -32,8 +30,6 @@ interface Props { browserFields: BrowserFields; id: string; dataProviders: DataProvider[]; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onChangeDroppableAndProvider: OnChangeDroppableAndProvider; onDataProviderEdited: OnDataProviderEdited; onDataProviderRemoved: OnDataProviderRemoved; onToggleDataProviderEnabled: OnToggleDataProviderEnabled; @@ -42,6 +38,8 @@ interface Props { } const DropTargetDataProvidersContainer = styled.div` + padding: 2px 0 4px 0; + .${IS_DRAGGING_CLASS_NAME} & .drop-target-data-providers { background: ${({ theme }) => rgba(theme.eui.euiColorSuccess, 0.1)}; border: 0.2rem dashed ${({ theme }) => theme.eui.euiColorSuccess}; @@ -60,9 +58,6 @@ const DropTargetDataProviders = styled.div` position: relative; border: 0.2rem dashed ${props => props.theme.eui.euiColorMediumShade}; border-radius: 5px; - display: flex; - flex-direction: column; - justify-content: center; margin: 5px 0 5px 0; min-height: 100px; overflow-y: auto; @@ -95,43 +90,46 @@ export const DataProviders = React.memo( browserFields, id, dataProviders, - onChangeDataProviderKqlQuery, - onChangeDroppableAndProvider, onDataProviderEdited, onDataProviderRemoved, onToggleDataProviderEnabled, onToggleDataProviderExcluded, show, - }) => ( - - - - {({ isLoading }) => ( - - {dataProviders != null && dataProviders.length ? ( - - ) : ( - - )} - - )} - - - - ) + }) => { + return ( + + + + {({ isLoading }) => ( + <> + {dataProviders != null && dataProviders.length ? ( + + ) : ( + + + + )} + + )} + + + + ); + } ); DataProviders.displayName = 'DataProviders'; diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx index e04aed17c6d67..859ced39ebc4f 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_badge.tsx @@ -10,9 +10,8 @@ import { isString } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; +import { ProviderContainer } from '../../drag_and_drop/provider_container'; import { getEmptyString } from '../../empty_value'; -import { WithCopyToClipboard } from '../../../lib/clipboard/with_copy_to_clipboard'; -import { WithHoverActions } from '../../with_hover_actions'; import { EXISTS_OPERATOR, QueryOperator } from './data_provider'; @@ -94,26 +93,13 @@ export const ProviderBadge = React.memo( const prefix = useMemo(() => (isExcluded ? {i18n.NOT} : null), [isExcluded]); - const title = useMemo(() => `${field}: "${formattedValue}"`, [field, formattedValue]); - - const hoverContent = useMemo( - () => ( - - ), - [field, val] - ); - - const badge = useCallback( - () => ( + return ( + ( )} - ), - [ - providerId, - field, - val, - classes, - title, - deleteFilter, - togglePopover, - formattedValue, - closeButtonProps, - prefix, - operator, - ] + ); - - return ; } ); diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and.tsx deleted file mode 100644 index badc92d00c174..0000000000000 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiFlexItem } from '@elastic/eui'; -import React from 'react'; - -import { AndOrBadge } from '../../and_or_badge'; -import { BrowserFields } from '../../../containers/source'; -import { - OnChangeDataProviderKqlQuery, - OnDataProviderEdited, - OnDataProviderRemoved, - OnToggleDataProviderEnabled, - OnToggleDataProviderExcluded, -} from '../events'; - -import { DataProvidersAnd, IS_OPERATOR } from './data_provider'; -import { ProviderItemBadge } from './provider_item_badge'; - -interface ProviderItemAndPopoverProps { - browserFields: BrowserFields; - dataProvidersAnd: DataProvidersAnd[]; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onDataProviderEdited: OnDataProviderEdited; - onDataProviderRemoved: OnDataProviderRemoved; - onToggleDataProviderEnabled: OnToggleDataProviderEnabled; - onToggleDataProviderExcluded: OnToggleDataProviderExcluded; - providerId: string; - timelineId: string; -} - -export class ProviderItemAnd extends React.PureComponent { - public render() { - const { - browserFields, - dataProvidersAnd, - onDataProviderEdited, - providerId, - timelineId, - } = this.props; - - return dataProvidersAnd.map((providerAnd: DataProvidersAnd, index: number) => ( - - - - - - this.deleteAndProvider(providerId, providerAnd.id)} - field={providerAnd.queryMatch.displayField || providerAnd.queryMatch.field} - kqlQuery={providerAnd.kqlQuery} - isEnabled={providerAnd.enabled} - isExcluded={providerAnd.excluded} - onDataProviderEdited={onDataProviderEdited} - operator={providerAnd.queryMatch.operator || IS_OPERATOR} - providerId={providerId} - timelineId={timelineId} - toggleEnabledProvider={() => - this.toggleEnabledAndProvider(providerId, !providerAnd.enabled, providerAnd.id) - } - toggleExcludedProvider={() => - this.toggleExcludedAndProvider(providerId, !providerAnd.excluded, providerAnd.id) - } - val={providerAnd.queryMatch.displayValue || providerAnd.queryMatch.value} - /> - - - )); - } - - private deleteAndProvider = (providerId: string, andProviderId: string) => { - this.props.onDataProviderRemoved(providerId, andProviderId); - }; - - private toggleEnabledAndProvider = ( - providerId: string, - enabled: boolean, - andProviderId: string - ) => { - this.props.onToggleDataProviderEnabled({ providerId, enabled, andProviderId }); - }; - - private toggleExcludedAndProvider = ( - providerId: string, - excluded: boolean, - andProviderId: string - ) => { - this.props.onToggleDataProviderExcluded({ providerId, excluded, andProviderId }); - }; -} diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and_drag_drop.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and_drag_drop.tsx deleted file mode 100644 index 3a691d2bbc621..0000000000000 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_and_drag_drop.tsx +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { rgba } from 'polished'; -import React, { useCallback } from 'react'; -import styled from 'styled-components'; - -import { AndOrBadge } from '../../and_or_badge'; -import { - OnChangeDataProviderKqlQuery, - OnChangeDroppableAndProvider, - OnDataProviderEdited, - OnDataProviderRemoved, - OnToggleDataProviderEnabled, - OnToggleDataProviderExcluded, -} from '../events'; - -import { BrowserFields } from '../../../containers/source'; - -import { DataProvider } from './data_provider'; -import { ProviderItemAnd } from './provider_item_and'; - -import * as i18n from './translations'; - -const DropAndTargetDataProvidersContainer = styled(EuiFlexItem)` - margin: 0px 8px; -`; - -DropAndTargetDataProvidersContainer.displayName = 'DropAndTargetDataProvidersContainer'; - -const DropAndTargetDataProviders = styled.div<{ hasAndItem: boolean }>` - min-width: 230px; - width: auto; - border: 0.1rem dashed ${props => props.theme.eui.euiColorSuccess}; - border-radius: 5px; - text-align: center; - padding: 3px 10px; - display: flex; - justify-content: center; - align-items: center; - ${props => - props.hasAndItem - ? `&:hover { - transition: background-color 0.7s ease; - background-color: ${() => rgba(props.theme.eui.euiColorSuccess, 0.2)}; - }` - : ''}; - cursor: ${({ hasAndItem }) => (!hasAndItem ? `default` : 'inherit')}; -`; - -DropAndTargetDataProviders.displayName = 'DropAndTargetDataProviders'; - -const NumberProviderAndBadge = (styled(EuiBadge)` - margin: 0px 5px; -` as unknown) as typeof EuiBadge; - -NumberProviderAndBadge.displayName = 'NumberProviderAndBadge'; - -interface ProviderItemDropProps { - browserFields: BrowserFields; - dataProvider: DataProvider; - mousePosition?: { x: number; y: number; boundLeft: number; boundTop: number }; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onChangeDroppableAndProvider: OnChangeDroppableAndProvider; - onDataProviderEdited: OnDataProviderEdited; - onDataProviderRemoved: OnDataProviderRemoved; - onToggleDataProviderEnabled: OnToggleDataProviderEnabled; - onToggleDataProviderExcluded: OnToggleDataProviderExcluded; - timelineId: string; -} - -export const ProviderItemAndDragDrop = React.memo( - ({ - browserFields, - dataProvider, - onChangeDataProviderKqlQuery, - onChangeDroppableAndProvider, - onDataProviderEdited, - onDataProviderRemoved, - onToggleDataProviderEnabled, - onToggleDataProviderExcluded, - timelineId, - }) => { - const onMouseEnter = useCallback(() => onChangeDroppableAndProvider(dataProvider.id), [ - onChangeDroppableAndProvider, - dataProvider.id, - ]); - const onMouseLeave = useCallback(() => onChangeDroppableAndProvider(''), [ - onChangeDroppableAndProvider, - ]); - const hasAndItem = dataProvider.and.length > 0; - return ( - - - - {hasAndItem && ( - - {dataProvider.and.length} - - )} - - {i18n.DROP_HERE_TO_ADD_AN} - - - - - - - ); - } -); - -ProviderItemAndDragDrop.displayName = 'ProviderItemAndDragDrop'; diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx index 2cc19537d6a63..b268315efb919 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/provider_item_badge.tsx @@ -5,14 +5,16 @@ */ import { noop } from 'lodash/fp'; -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; import { BrowserFields } from '../../../containers/source'; import { OnDataProviderEdited } from '../events'; import { ProviderBadge } from './provider_badge'; import { ProviderItemActions } from './provider_item_actions'; -import { QueryOperator } from './data_provider'; +import { DataProvidersAnd, QueryOperator } from './data_provider'; +import { dragAndDropActions } from '../../../store/drag_and_drop'; import { TimelineContext } from '../timeline_context'; interface ProviderItemBadgeProps { @@ -26,6 +28,7 @@ interface ProviderItemBadgeProps { onDataProviderEdited?: OnDataProviderEdited; operator: QueryOperator; providerId: string; + register?: DataProvidersAnd; timelineId?: string; toggleEnabledProvider: () => void; toggleExcludedProvider: () => void; @@ -44,6 +47,7 @@ export const ProviderItemBadge = React.memo( onDataProviderEdited, operator, providerId, + register, timelineId, toggleEnabledProvider, toggleExcludedProvider, @@ -69,6 +73,31 @@ export const ProviderItemBadge = React.memo( closePopover(); }, [toggleExcludedProvider]); + const [providerRegistered, setProviderRegistered] = useState(false); + + const dispatch = useDispatch(); + + useEffect(() => { + // optionally register the provider if provided + if (!providerRegistered && register != null) { + dispatch(dragAndDropActions.registerProvider({ provider: { ...register, and: [] } })); + setProviderRegistered(true); + } + }, [providerRegistered, dispatch, register, setProviderRegistered]); + + const unRegisterProvider = useCallback(() => { + if (providerRegistered && register != null) { + dispatch(dragAndDropActions.unRegisterProvider({ id: register.id })); + } + }, [providerRegistered, dispatch, register]); + + useEffect( + () => () => { + unRegisterProvider(); + }, + [] + ); + return ( {({ isLoading }) => ( diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/providers.test.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/providers.test.tsx index 0c8a6932adf91..43e84bac508ea 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/providers.test.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/providers.test.tsx @@ -14,7 +14,7 @@ import { FilterManager } from '../../../../../../../src/plugins/data/public'; import { TimelineContext } from '../timeline_context'; import { mockDataProviders } from './mock/mock_data_providers'; -import { getDraggableId, Providers } from './providers'; +import { Providers } from './providers'; import { DELETE_CLASS_NAME, ENABLE_CLASS_NAME, EXCLUDE_CLASS_NAME } from './provider_item_actions'; import { useMountAppended } from '../../../utils/use_mount_appended'; @@ -32,8 +32,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -51,8 +49,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -80,8 +76,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -107,8 +101,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -136,8 +128,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -170,8 +160,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -197,14 +185,6 @@ describe('Providers', () => { }); }); - describe('#getDraggableId', () => { - test('it returns the expected id', () => { - expect(getDraggableId({ id: 'timeline1', dataProviderId: 'abcd' })).toEqual( - 'draggableId.timeline.timeline1.dataProvider.abcd' - ); - }); - }); - describe('#onToggleDataProviderEnabled', () => { test('it invokes the onToggleDataProviderEnabled callback when you click on the option "Temporary disable" in the provider menu', () => { const mockOnToggleDataProviderEnabled = jest.fn(); @@ -215,8 +195,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled} @@ -252,8 +230,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled} @@ -290,8 +266,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -330,8 +304,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -370,8 +342,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={dataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -403,8 +373,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -439,8 +407,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={mockDataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={mockOnDataProviderRemoved} onToggleDataProviderEnabled={jest.fn()} @@ -475,8 +441,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={dataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled} @@ -520,8 +484,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={dataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled} @@ -561,8 +523,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={dataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -606,8 +566,6 @@ describe('Providers', () => { browserFields={{}} dataProviders={dataProviders} id="foo" - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/providers.tsx b/x-pack/plugins/siem/public/components/timeline/data_providers/providers.tsx index bfe99f6920e66..8d9d0c69d53cd 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/providers.tsx +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/providers.tsx @@ -5,32 +5,35 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiFormHelpText } from '@elastic/eui'; -import React from 'react'; -import { Draggable } from 'react-beautiful-dnd'; -import styled from 'styled-components'; +import { rgba } from 'polished'; +import React, { useMemo } from 'react'; +import { Draggable, DraggingStyle, Droppable, NotDraggingStyle } from 'react-beautiful-dnd'; +import styled, { css } from 'styled-components'; +import { AndOrBadge } from '../../and_or_badge'; +import { BrowserFields } from '../../../containers/source'; +import { + getTimelineProviderDroppableId, + IS_DRAGGING_CLASS_NAME, + getTimelineProviderDraggableId, +} from '../../drag_and_drop/helpers'; import { - OnChangeDataProviderKqlQuery, - OnChangeDroppableAndProvider, OnDataProviderEdited, OnDataProviderRemoved, OnToggleDataProviderEnabled, OnToggleDataProviderExcluded, } from '../events'; -import { BrowserFields } from '../../../containers/source'; -import { DataProvider, IS_OPERATOR } from './data_provider'; -import { Empty } from './empty'; -import { ProviderItemAndDragDrop } from './provider_item_and_drag_drop'; +import { DataProvider, DataProvidersAnd, IS_OPERATOR } from './data_provider'; +import { EMPTY_GROUP, flattenIntoAndGroups } from './helpers'; import { ProviderItemBadge } from './provider_item_badge'; -import * as i18n from './translations'; + +export const EMPTY_PROVIDERS_GROUP_CLASS_NAME = 'empty-providers-group'; interface Props { browserFields: BrowserFields; id: string; dataProviders: DataProvider[]; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onChangeDroppableAndProvider: OnChangeDroppableAndProvider; onDataProviderEdited: OnDataProviderEdited; onDataProviderRemoved: OnDataProviderRemoved; onToggleDataProviderEnabled: OnToggleDataProviderEnabled; @@ -42,68 +45,66 @@ interface Props { * (growth causes layout thrashing) when the AND drop target in a row * of data providers is revealed. */ -const ROW_OF_DATA_PROVIDERS_HEIGHT = 43; // px - -const PanelProviders = styled.div` - position: relative; - display: flex; - flex-direction: row; - min-height: 100px; - padding: 5px 10px 15px 0px; - overflow-y: auto; - align-items: stretch; - justify-content: flex-start; -`; +const ROW_OF_DATA_PROVIDERS_HEIGHT = 36; // px -PanelProviders.displayName = 'PanelProviders'; +const listStyle: React.CSSProperties = { + alignItems: 'center', + display: 'flex', + height: `${ROW_OF_DATA_PROVIDERS_HEIGHT}px`, + minWidth: '125px', +}; -const PanelProvidersGroupContainer = styled(EuiFlexGroup)` - position: relative; - flex-grow: unset; +const getItemStyle = ( + draggableStyle: DraggingStyle | NotDraggingStyle | undefined +): React.CSSProperties => ({ + ...draggableStyle, + userSelect: 'none', +}); - .euiFlexItem { - flex: 1 0 auto; - } +const DroppableContainer = styled.div` + height: ${ROW_OF_DATA_PROVIDERS_HEIGHT}px; - .euiFlexItem--flexGrowZero { - flex: 0 0 auto; + .${IS_DRAGGING_CLASS_NAME} &:hover { + background-color: ${({ theme }) => rgba(theme.eui.euiColorSuccess, 0.2)} !important; } `; -PanelProvidersGroupContainer.displayName = 'PanelProvidersGroupContainer'; +const Parens = styled.span` + ${({ theme }) => css` + color: ${theme.eui.euiColorMediumShade}; + font-size: 32px; + padding: 2px; + user-select: none; + `} +`; -/** A row of data providers in the timeline drop zone */ -const PanelProviderGroupContainer = styled(EuiFlexGroup)` - height: ${ROW_OF_DATA_PROVIDERS_HEIGHT}px; - min-height: ${ROW_OF_DATA_PROVIDERS_HEIGHT}px; - margin: 5px 0px; +const AndOrBadgeContainer = styled.div<{ hideBadge: boolean }>` + span { + visibility: ${({ hideBadge }) => (hideBadge ? 'hidden' : 'inherit')}; + } `; -PanelProviderGroupContainer.displayName = 'PanelProviderGroupContainer'; +const LastAndOrBadgeInGroup = styled.div` + display: none; -const PanelProviderItemContainer = styled(EuiFlexItem)` - position: relative; + .${IS_DRAGGING_CLASS_NAME} & { + display: initial; + } `; -PanelProviderItemContainer.displayName = 'PanelProviderItemContainer'; +const OrFlexItem = styled(EuiFlexItem)` + padding-left: 9px; +`; const TimelineEuiFormHelpText = styled(EuiFormHelpText)` padding-top: 0px; position: absolute; bottom: 0px; - left: 5px; + left: 4px; `; TimelineEuiFormHelpText.displayName = 'TimelineEuiFormHelpText'; -interface GetDraggableIdParams { - id: string; - dataProviderId: string; -} - -export const getDraggableId = ({ id, dataProviderId }: GetDraggableIdParams): string => - `draggableId.timeline.${id}.dataProvider.${dataProviderId}`; - /** * Renders an interactive card representation of the data providers. It also * affords uniform UI controls for the following actions: @@ -116,104 +117,151 @@ export const Providers = React.memo( browserFields, id, dataProviders, - onChangeDataProviderKqlQuery, - onChangeDroppableAndProvider, onDataProviderEdited, onDataProviderRemoved, onToggleDataProviderEnabled, onToggleDataProviderExcluded, - }) => ( - - 0} /> - - - {dataProviders.map((dataProvider, i) => { - const deleteProvider = () => onDataProviderRemoved(dataProvider.id); - const toggleEnabledProvider = () => - onToggleDataProviderEnabled({ - providerId: dataProvider.id, - enabled: !dataProvider.enabled, - }); - const toggleExcludedProvider = () => - onToggleDataProviderExcluded({ - providerId: dataProvider.id, - excluded: !dataProvider.excluded, - }); - return ( - // Providers are a special drop target that can't be drag-and-dropped - // to another destination, so it doesn't use our DraggableWrapper - { + // Transform the dataProviders into flattened groups, and append an empty group + const dataProviderGroups: DataProvidersAnd[][] = useMemo( + () => [...flattenIntoAndGroups(dataProviders), ...EMPTY_GROUP], + [dataProviders] + ); + + return ( + <> + {dataProviderGroups.map((group, groupIndex) => ( + + + + + + + + {'('} + + + - - ( + - {provided => ( -
( + - -
- )} -
-
- - - -
- ); - })} -
-
- - - {i18n.DROP_HERE} {i18n.TO_BUILD_AN} {i18n.OR.toLocaleUpperCase()} {i18n.QUERY} - - -
- ) + {(provided, snapshot) => ( +
+ + + 0 ? dataProvider.id : undefined} + browserFields={browserFields} + deleteProvider={() => + index > 0 + ? onDataProviderRemoved(group[0].id, dataProvider.id) + : onDataProviderRemoved(dataProvider.id) + } + field={ + index > 0 + ? dataProvider.queryMatch.displayField ?? + dataProvider.queryMatch.field + : group[0].queryMatch.displayField ?? + group[0].queryMatch.field + } + kqlQuery={index > 0 ? dataProvider.kqlQuery : group[0].kqlQuery} + isEnabled={index > 0 ? dataProvider.enabled : group[0].enabled} + isExcluded={index > 0 ? dataProvider.excluded : group[0].excluded} + onDataProviderEdited={onDataProviderEdited} + operator={ + index > 0 + ? dataProvider.queryMatch.operator ?? IS_OPERATOR + : group[0].queryMatch.operator ?? IS_OPERATOR + } + register={dataProvider} + providerId={index > 0 ? group[0].id : dataProvider.id} + timelineId={id} + toggleEnabledProvider={() => + index > 0 + ? onToggleDataProviderEnabled({ + providerId: group[0].id, + enabled: !dataProvider.enabled, + andProviderId: dataProvider.id, + }) + : onToggleDataProviderEnabled({ + providerId: dataProvider.id, + enabled: !dataProvider.enabled, + }) + } + toggleExcludedProvider={() => + index > 0 + ? onToggleDataProviderExcluded({ + providerId: group[0].id, + excluded: !dataProvider.excluded, + andProviderId: dataProvider.id, + }) + : onToggleDataProviderExcluded({ + providerId: dataProvider.id, + excluded: !dataProvider.excluded, + }) + } + val={ + dataProvider.queryMatch.displayValue ?? + dataProvider.queryMatch.value + } + /> + + + {!snapshot.isDragging && + (index < group.length - 1 ? ( + + ) : ( + + + + ))} + + +
+ )} + + ))} + {droppableProvided.placeholder} + + )} + + + + {')'} + + + ))} + + ); + } ); Providers.displayName = 'Providers'; diff --git a/x-pack/plugins/siem/public/components/timeline/data_providers/translations.ts b/x-pack/plugins/siem/public/components/timeline/data_providers/translations.ts index eec12177b8b72..56628502f5550 100644 --- a/x-pack/plugins/siem/public/components/timeline/data_providers/translations.ts +++ b/x-pack/plugins/siem/public/components/timeline/data_providers/translations.ts @@ -83,7 +83,7 @@ export const INCLUDE_DATA_PROVIDER = i18n.translate( ); export const NOT = i18n.translate('xpack.siem.dataProviders.not', { - defaultMessage: 'not', + defaultMessage: 'NOT', }); export const OR = i18n.translate('xpack.siem.dataProviders.or', { diff --git a/x-pack/plugins/siem/public/components/timeline/header/__snapshots__/index.test.tsx.snap b/x-pack/plugins/siem/public/components/timeline/header/__snapshots__/index.test.tsx.snap index 42a1d4cd7f0f0..1182cf4f44bc8 100644 --- a/x-pack/plugins/siem/public/components/timeline/header/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/siem/public/components/timeline/header/__snapshots__/index.test.tsx.snap @@ -139,8 +139,6 @@ exports[`Header rendering renders correctly against snapshot 1`] = ` ] } id="foo" - onChangeDataProviderKqlQuery={[MockFunction]} - onChangeDroppableAndProvider={[MockFunction]} onDataProviderEdited={[MockFunction]} onDataProviderRemoved={[MockFunction]} onToggleDataProviderEnabled={[MockFunction]} diff --git a/x-pack/plugins/siem/public/components/timeline/header/index.test.tsx b/x-pack/plugins/siem/public/components/timeline/header/index.test.tsx index 6f2053488f69b..7da76df497768 100644 --- a/x-pack/plugins/siem/public/components/timeline/header/index.test.tsx +++ b/x-pack/plugins/siem/public/components/timeline/header/index.test.tsx @@ -33,8 +33,6 @@ describe('Header', () => { filterManager={new FilterManager(mockUiSettingsForFilterManager)} id="foo" indexPattern={indexPattern} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -55,8 +53,6 @@ describe('Header', () => { filterManager={new FilterManager(mockUiSettingsForFilterManager)} id="foo" indexPattern={indexPattern} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} @@ -79,8 +75,6 @@ describe('Header', () => { filterManager={new FilterManager(mockUiSettingsForFilterManager)} id="foo" indexPattern={indexPattern} - onChangeDataProviderKqlQuery={jest.fn()} - onChangeDroppableAndProvider={jest.fn()} onDataProviderEdited={jest.fn()} onDataProviderRemoved={jest.fn()} onToggleDataProviderEnabled={jest.fn()} diff --git a/x-pack/plugins/siem/public/components/timeline/header/index.tsx b/x-pack/plugins/siem/public/components/timeline/header/index.tsx index 99964c955bafe..58e6b6e837249 100644 --- a/x-pack/plugins/siem/public/components/timeline/header/index.tsx +++ b/x-pack/plugins/siem/public/components/timeline/header/index.tsx @@ -12,8 +12,6 @@ import deepEqual from 'fast-deep-equal'; import { DataProviders } from '../data_providers'; import { DataProvider } from '../data_providers/data_provider'; import { - OnChangeDataProviderKqlQuery, - OnChangeDroppableAndProvider, OnDataProviderEdited, OnDataProviderRemoved, OnToggleDataProviderEnabled, @@ -30,8 +28,6 @@ interface Props { filterManager: FilterManager; id: string; indexPattern: IIndexPattern; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onChangeDroppableAndProvider: OnChangeDroppableAndProvider; onDataProviderEdited: OnDataProviderEdited; onDataProviderRemoved: OnDataProviderRemoved; onToggleDataProviderEnabled: OnToggleDataProviderEnabled; @@ -46,8 +42,6 @@ const TimelineHeaderComponent: React.FC = ({ indexPattern, dataProviders, filterManager, - onChangeDataProviderKqlQuery, - onChangeDroppableAndProvider, onDataProviderEdited, onDataProviderRemoved, onToggleDataProviderEnabled, @@ -65,18 +59,19 @@ const TimelineHeaderComponent: React.FC = ({ size="s" /> )} - + {show && ( + + )} + ( start, updateDataProviderEnabled, updateDataProviderExcluded, - updateDataProviderKqlQuery, - updateHighlightedDropAndProviderId, updateItemsPerPage, upsertColumn, usersViewing, @@ -120,21 +116,11 @@ const StatefulTimelineComponent = React.memo( [id] ); - const onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery = useCallback( - ({ providerId, kqlQuery }) => updateDataProviderKqlQuery!({ id, kqlQuery, providerId }), - [id] - ); - const onChangeItemsPerPage: OnChangeItemsPerPage = useCallback( itemsChangedPerPage => updateItemsPerPage!({ id, itemsPerPage: itemsChangedPerPage }), [id] ); - const onChangeDroppableAndProvider: OnChangeDroppableAndProvider = useCallback( - providerId => updateHighlightedDropAndProviderId!({ id, providerId }), - [id] - ); - const toggleColumn = useCallback( (column: ColumnHeaderOptions) => { const exists = columns.findIndex(c => c.id === column.id) !== -1; @@ -182,8 +168,6 @@ const StatefulTimelineComponent = React.memo( kqlMode={kqlMode} kqlQueryExpression={kqlQueryExpression} loadingIndexName={loading} - onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery} - onChangeDroppableAndProvider={onChangeDroppableAndProvider} onChangeItemsPerPage={onChangeItemsPerPage} onClose={onClose} onDataProviderEdited={onDataProviderEditedLocal} diff --git a/x-pack/plugins/siem/public/components/timeline/timeline.test.tsx b/x-pack/plugins/siem/public/components/timeline/timeline.test.tsx index 22f1c525a6c2a..0d0ce79c77be7 100644 --- a/x-pack/plugins/siem/public/components/timeline/timeline.test.tsx +++ b/x-pack/plugins/siem/public/components/timeline/timeline.test.tsx @@ -65,8 +65,6 @@ describe('Timeline', () => { kqlMode: 'search' as TimelineComponentProps['kqlMode'], kqlQueryExpression: '', loadingIndexName: false, - onChangeDataProviderKqlQuery: jest.fn(), - onChangeDroppableAndProvider: jest.fn(), onChangeItemsPerPage: jest.fn(), onClose: jest.fn(), onDataProviderEdited: jest.fn(), diff --git a/x-pack/plugins/siem/public/components/timeline/timeline.tsx b/x-pack/plugins/siem/public/components/timeline/timeline.tsx index 10f10b1a86f1e..cc3116235557f 100644 --- a/x-pack/plugins/siem/public/components/timeline/timeline.tsx +++ b/x-pack/plugins/siem/public/components/timeline/timeline.tsx @@ -20,8 +20,6 @@ import { Sort } from './body/sort'; import { StatefulBody } from './body/stateful_body'; import { DataProvider } from './data_providers/data_provider'; import { - OnChangeDataProviderKqlQuery, - OnChangeDroppableAndProvider, OnChangeItemsPerPage, OnDataProviderRemoved, OnDataProviderEdited, @@ -99,8 +97,6 @@ export interface Props { kqlMode: KqlMode; kqlQueryExpression: string; loadingIndexName: boolean; - onChangeDataProviderKqlQuery: OnChangeDataProviderKqlQuery; - onChangeDroppableAndProvider: OnChangeDroppableAndProvider; onChangeItemsPerPage: OnChangeItemsPerPage; onClose: () => void; onDataProviderEdited: OnDataProviderEdited; @@ -132,8 +128,6 @@ export const TimelineComponent: React.FC = ({ kqlMode, kqlQueryExpression, loadingIndexName, - onChangeDataProviderKqlQuery, - onChangeDroppableAndProvider, onChangeItemsPerPage, onClose, onDataProviderEdited, @@ -185,8 +179,6 @@ export const TimelineComponent: React.FC = ({ indexPattern={indexPattern} dataProviders={dataProviders} filterManager={filterManager} - onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery} - onChangeDroppableAndProvider={onChangeDroppableAndProvider} onDataProviderEdited={onDataProviderEdited} onDataProviderRemoved={onDataProviderRemoved} onToggleDataProviderEnabled={onToggleDataProviderEnabled} diff --git a/x-pack/plugins/siem/public/hooks/translations.ts b/x-pack/plugins/siem/public/hooks/translations.ts index ba3ec40df466a..40db748a3e1ac 100644 --- a/x-pack/plugins/siem/public/hooks/translations.ts +++ b/x-pack/plugins/siem/public/hooks/translations.ts @@ -6,6 +6,12 @@ import { i18n } from '@kbn/i18n'; +export const ADDED_TO_TIMELINE_MESSAGE = (fieldOrValue: string) => + i18n.translate('xpack.siem.hooks.useAddToTimeline.addedFieldMessage', { + values: { fieldOrValue }, + defaultMessage: `Added {fieldOrValue} to timeline`, + }); + export const STATUS_CODE = i18n.translate( 'xpack.siem.components.ml.api.errors.statusCodeFailureTitle', { diff --git a/x-pack/plugins/siem/public/hooks/use_add_to_timeline.tsx b/x-pack/plugins/siem/public/hooks/use_add_to_timeline.tsx new file mode 100644 index 0000000000000..be0ddb153457e --- /dev/null +++ b/x-pack/plugins/siem/public/hooks/use_add_to_timeline.tsx @@ -0,0 +1,165 @@ +/* + * 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 d3 from 'd3'; +import { useCallback } from 'react'; +import { DraggableId, FluidDragActions, Position, SensorAPI } from 'react-beautiful-dnd'; + +import { IS_DRAGGING_CLASS_NAME } from '../components/drag_and_drop/helpers'; +import { HIGHLIGHTED_DROP_TARGET_CLASS_NAME } from '../components/timeline/data_providers/empty'; +import { EMPTY_PROVIDERS_GROUP_CLASS_NAME } from '../components/timeline/data_providers/providers'; + +let _sensorApiSingleton: SensorAPI; + +/** + * This hook is passed (in an array) to the `sensors` prop of the + * `react-beautiful-dnd` `DragDropContext` component. Example: + * + * ``` + + {children} + * + * ``` + * + * As a side effect of registering this hook with the `DragDropContext`, + * the `SensorAPI` singleton is initialized. This singleton is used + * by the `useAddToTimeline` hook. + */ +export const useAddToTimelineSensor = (api: SensorAPI) => { + _sensorApiSingleton = api; +}; + +/** + * Returns the position of the specified element + */ +const getPosition = (element: Element): Position => { + const rect = element.getBoundingClientRect(); + + return { x: rect.left, y: rect.top }; +}; + +/** + * Returns the position of one of the following timeline drop targets + * (in the following order of preference): + * 1) The "Drop anything highlighted..." drop target + * 2) The persistent "empty" data provider group drop target + * 3) `null`, because none of the above targets exist (an error state) + */ +export const getDropTargetCoordinate = (): Position | null => { + // The placeholder in the "Drop anything highlighted here to build an OR query": + const highlighted = document.querySelector(`.${HIGHLIGHTED_DROP_TARGET_CLASS_NAME}`); + + if (highlighted != null) { + return getPosition(highlighted); + } + + // If at least one provider has been added to the timeline, the "Drop anything + // highlighted..." drop target won't be visible, so we need to drop into the + // empty group instead: + const emptyGroup = document.querySelector(`.${EMPTY_PROVIDERS_GROUP_CLASS_NAME}`); + + if (emptyGroup != null) { + return getPosition(emptyGroup); + } + + return null; +}; + +/** + * Returns the coordinates of the specified draggable + */ +export const getDraggableCoordinate = (draggableId: DraggableId): Position | null => { + // The placeholder in the "Drop anything highlighted here to build an OR query": + const draggable = document.querySelector(`[data-rbd-draggable-id="${draggableId}"]`); + + if (draggable != null) { + return getPosition(draggable); + } + + return null; +}; + +/** + * Animates a draggable via `requestAnimationFrame` + */ +export const animate = ({ + drag, + fieldName, + values, +}: { + drag: FluidDragActions; + fieldName: string; + values: Position[]; +}) => { + requestAnimationFrame(() => { + if (values.length === 0) { + setTimeout(() => drag.drop(), 0); // schedule the drop the next time around + return; + } + + drag.move(values[0]); + + animate({ + drag, + fieldName, + values: values.slice(1), + }); + }); +}; + +/** + * This hook animates a draggable data provider to the timeline + */ +export const useAddToTimeline = ({ + draggableId, + fieldName, +}: { + draggableId: DraggableId | undefined; + fieldName: string; +}) => { + const startDragToTimeline = useCallback(() => { + if (_sensorApiSingleton == null) { + throw new TypeError( + 'To use this hook, the companion `useAddToTimelineSensor` hook must be registered in the `sensors` prop of the `DragDropContext`.' + ); + } + + if (draggableId == null) { + // A request to start the animation should not have been made, because + // no draggableId was provided + return; + } + + // add the dragging class, which will show the flyout data providers (if the flyout button is being displayed): + document.body.classList.add(IS_DRAGGING_CLASS_NAME); + + // start the animation after the flyout data providers are visible: + setTimeout(() => { + const draggableCoordinate = getDraggableCoordinate(draggableId); + const dropTargetCoordinate = getDropTargetCoordinate(); + const preDrag = _sensorApiSingleton.tryGetLock(draggableId); + + if (draggableCoordinate != null && dropTargetCoordinate != null && preDrag != null) { + const steps = 10; + const points = d3.range(steps + 1).map(i => ({ + x: d3.interpolate(draggableCoordinate.x, dropTargetCoordinate.x)(i * 0.1), + y: d3.interpolate(draggableCoordinate.y, dropTargetCoordinate.y)(i * 0.1), + })); + + const drag = preDrag.fluidLift(draggableCoordinate); + animate({ + drag, + fieldName, + values: points, + }); + } else { + document.body.classList.remove(IS_DRAGGING_CLASS_NAME); // it was not possible to perform a drag and drop + } + }, 0); + }, [_sensorApiSingleton, draggableId]); + + return startDragToTimeline; +}; diff --git a/x-pack/plugins/siem/public/hooks/use_providers_portal.tsx b/x-pack/plugins/siem/public/hooks/use_providers_portal.tsx new file mode 100644 index 0000000000000..1099215f755ee --- /dev/null +++ b/x-pack/plugins/siem/public/hooks/use_providers_portal.tsx @@ -0,0 +1,20 @@ +/* + * 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 { useState } from 'react'; +import { createPortalNode } from 'react-reverse-portal'; + +/** + * A singleton portal for rendering the draggable groups of providers in the + * header of the timeline, or in the animated flyout + */ +const proivdersPortalNodeSingleton = createPortalNode(); + +export const useProvidersPortal = () => { + const [proivdersPortalNode] = useState(proivdersPortalNodeSingleton); + + return proivdersPortalNode; +}; From f5e8f3d3c20e2f70438488b0871f0e9fc325ea61 Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Tue, 5 May 2020 15:32:18 -0700 Subject: [PATCH 46/72] docs: update timeline (#65182) --- docs/apm/spans.asciidoc | 33 ++++++++++++++++++++++++--------- docs/apm/traces.asciidoc | 24 +----------------------- docs/apm/transactions.asciidoc | 2 +- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/docs/apm/spans.asciidoc b/docs/apm/spans.asciidoc index 2eed339160fc4..c35fb115d2db4 100644 --- a/docs/apm/spans.asciidoc +++ b/docs/apm/spans.asciidoc @@ -1,38 +1,53 @@ [role="xpack"] [[spans]] -=== Span timeline +=== Trace sample timeline -TIP: A {apm-overview-ref-v}/transaction-spans.html[span] is the duration of a single event. -Spans are automatically captured by APM agents, and you can also define custom spans. -Each span has a type and is defined by a different color in the timeline/waterfall visualization. - -The span timeline visualization is a bird's-eye view of what your application was doing while it was trying to respond to the request that came in. +The trace sample timeline visualization is a bird's-eye view of what your application was doing while it was trying to respond to a request. This makes it useful for visualizing where the selected transaction spent most of its time. [role="screenshot"] image::apm/images/apm-transaction-sample.png[Example of distributed trace colors in the APM app in Kibana] View a span in detail by clicking on it in the timeline waterfall. -When you click on an SQL Select database query, +For example, when you click on an SQL Select database query, the information displayed includes the actual SQL that was executed, how long it took, and the percentage of the trace's total time. You also get a stack trace, which shows the SQL query in your code. Finally, APM knows which files are your code and which are just modules or libraries that you've installed. These library frames will be minimized by default in order to show you the most relevant stack trace. +TIP: A {apm-overview-ref-v}/transaction-spans.html[span] is the duration of a single event. +Spans are automatically captured by APM agents, and you can also define custom spans. +Each span has a type and is defined by a different color in the timeline/waterfall visualization. + [role="screenshot"] image::apm/images/apm-span-detail.png[Example view of a span detail in the APM app in Kibana] -If your span timeline is colorful, it's indicative of a <>. +[float] +[[distributed-tracing]] +==== Distributed tracing + +If your trace sample timeline is colorful, it's indicative of a distributed trace. Services in a distributed trace are separated by color and listed in the order they occur. [role="screenshot"] image::apm/images/apm-services-trace.png[Example of distributed trace colors in the APM app in Kibana] -Don't forget; a distributed trace includes more than one transaction. +As application architectures are shifting from monolithic to more distributed, service-based architectures, +distributed tracing has become a crucial feature of modern application performance monitoring. +It allows you to trace requests through your service architecture automatically, and visualize those traces in one single view in the APM app. +From initial web requests to your front-end service, to queries made to your back-end services, +this makes finding possible bottlenecks throughout your application much easier and faster. + +[role="screenshot"] +image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM app in Kibana] + +Don't forget; by definition, a distributed trace includes more than one transaction. When viewing these distributed traces in the timeline waterfall, you'll see this image:apm/images/transaction-icon.png[APM icon] icon, which indicates the next transaction in the trace. These transactions can be expanded and viewed in detail by clicking on them. After exploring these traces, you can return to the full trace by clicking *View full trace*. + +TIP: Distributed tracing is supported by all APM agents, and there's no additional configuration needed. diff --git a/docs/apm/traces.asciidoc b/docs/apm/traces.asciidoc index 8eef3d9bed4db..52b4b618de466 100644 --- a/docs/apm/traces.asciidoc +++ b/docs/apm/traces.asciidoc @@ -4,7 +4,7 @@ TIP: Traces link together related transactions to show an end-to-end performance of how a request was served and which services were part of it. -In addition to the Traces overview, you can view your application traces in the <>. +In addition to the Traces overview, you can view your application traces in the <>. The *Traces* overview displays the entry transaction for all traces in your application. If you're using <>, this view is key to finding the critical paths within your application. @@ -17,25 +17,3 @@ If there's a particular endpoint you're worried about, you can click on it to vi [role="screenshot"] image::apm/images/apm-traces.png[Example view of the Traces overview in APM app in Kibana] - -[float] -[[distributed-tracing]] -==== Distributed tracing - -Elastic APM supports distributed tracing. -Distributed tracing is a key feature of modern application performance monitoring as application architectures are shifting from monolithic to more distributed, -service-based architectures. - -Distributed tracing allows APM users to automatically trace requests all the way through the service architecture, -and visualize those traces in one single view in the APM app. -This is accomplished by tracing all of the requests, from the initial web request to your front-end service, -to queries made to your back-end services. -This makes finding possible bottlenecks throughout your application much easier and faster. - -By definition, a distributed trace includes more than one transaction. -You can use the <> to view a waterfall display of all of the transactions from individual services that are connected in a trace. - -[role="screenshot"] -image::apm/images/apm-distributed-tracing.png[Example view of the distributed tracing in APM app in Kibana] - -TIP: Distributed tracing is supported by all APM agents, and there's no additional configuration needed. \ No newline at end of file diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index 2e1022e6d684c..8012c9108ca5e 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -95,7 +95,7 @@ It's the requests on the right, the ones taking longer than average, that we pro When you select one of these buckets, you're presented with up to ten trace samples. -Each sample has a span timeline waterfall that shows what a typical request in that bucket was doing. +Each sample has a trace timeline waterfall that shows what a typical request in that bucket was doing. By investigating this timeline waterfall, we can hopefully determine _why_ this request was slow and then implement a fix. [role="screenshot"] From ee9c1a0ba11d0027de695c4b24381e54eca9a16c Mon Sep 17 00:00:00 2001 From: John Schulz Date: Tue, 5 May 2020 18:58:54 -0400 Subject: [PATCH 47/72] [Ingest Manager] Use cloudId for ES & Kibana URLs if available. (#65366) * Use cloudId for ES & Kibana URLs if available. * Add tests and a missing return * Use console.debug for consistency --- .../common/services/decode_cloud_id.test.ts | 100 ++++++++++++++++++ .../common/services/decode_cloud_id.ts | 65 ++++++++++++ .../ingest_manager/common/services/index.ts | 1 + .../ingest_manager/common/types/index.ts | 1 - x-pack/plugins/ingest_manager/server/index.ts | 2 +- .../ingest_manager/server/services/output.ts | 9 +- .../ingest_manager/server/services/setup.ts | 9 +- 7 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts create mode 100644 x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts diff --git a/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts b/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts new file mode 100644 index 0000000000000..dcec54f47440a --- /dev/null +++ b/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.test.ts @@ -0,0 +1,100 @@ +/* + * 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 { decodeCloudId } from './decode_cloud_id'; + +describe('Ingest Manager - decodeCloudId', () => { + it('parses various CloudID formats', () => { + const tests = [ + { + cloudID: + 'staging:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==', + expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443', + expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443', + }, + { + cloudID: + 'dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==', + expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443', + expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443', + }, + { + cloudID: + ':dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==', + expectedEsURL: 'https://cec6f261a74bf24ce33bb8811b84294f.us-east-1.aws.found.io:443', + expectedKibanaURL: 'https://c6c2ca6d042249af0cc7d7a9e9625743.us-east-1.aws.found.io:443', + }, + { + cloudID: + 'gcp-cluster:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZmNlJDBjZDVjZDU2OGVlYmU1M2M4OWViN2NhZTViYWM4YjM3', + expectedEsURL: 'https://8a0283af041f195f7729bc04c66a0fce.us-central1.gcp.cloud.es.io:443', + expectedKibanaURL: + 'https://0cd5cd568eebe53c89eb7cae5bac8b37.us-central1.gcp.cloud.es.io:443', + }, + { + cloudID: + 'custom-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA=', + expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243', + expectedKibanaURL: + 'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9243', + }, + { + cloudID: + 'different-es-kb-port:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==', + expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243', + expectedKibanaURL: + 'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244', + }, + { + cloudID: + 'only-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwOjkyNDQ=', + expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443', + expectedKibanaURL: + 'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244', + }, + { + cloudID: + 'host-and-kb-set:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvOjkyNDMkYWMzMWViYjkwMjQxNzczMTU3MDQzYzM0ZmQyNmZkNDYkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA==', + expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:9243', + expectedKibanaURL: + 'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:9244', + }, + { + cloudID: + 'extra-items:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2JGE0YzA2MjMwZTQ4YzhmY2U3YmU4OGEwNzRhM2JiM2UwJGFub3RoZXJpZCRhbmRhbm90aGVy', + expectedEsURL: 'https://ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io:443', + expectedKibanaURL: + 'https://a4c06230e48c8fce7be88a074a3bb3e0.us-central1.gcp.cloud.es.io:443', + }, + ]; + + for (const test of tests) { + const decoded = decodeCloudId(test.cloudID); + expect(decoded).toBeTruthy(); + expect(decoded?.elasticsearchUrl === test.expectedEsURL).toBe(true); + expect(decoded?.kibanaUrl === test.expectedKibanaURL).toBe(true); + } + }); + + it('returns undefined for invalid formats', () => { + const tests = [ + { + cloudID: + 'staging:garbagedXMtZWFzdC0xLmF3cy5mb3VuZC5pbyRjZWM2ZjI2MWE3NGJmMjRjZTMzYmI4ODExYjg0Mjk0ZiRjNmMyY2E2ZDA0MjI0OWFmMGNjN2Q3YTllOTYyNTc0Mw==', + errorMsg: 'base64 decoding failed', + }, + { + cloudID: 'dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJDhhMDI4M2FmMDQxZjE5NWY3NzI5YmMwNGM2NmEwZg==', + errorMsg: 'Expected at least 3 parts', + }, + ]; + + for (const test of tests) { + const decoded = decodeCloudId(test.cloudID); + expect(decoded).toBe(undefined); + // decodeCloudId currently only logs; not throws errors + } + }); +}); diff --git a/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts b/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts new file mode 100644 index 0000000000000..67389e554ed24 --- /dev/null +++ b/x-pack/plugins/ingest_manager/common/services/decode_cloud_id.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +// decodeCloudId decodes the c.id into c.esURL and c.kibURL +export function decodeCloudId( + cid: string +): + | { + host: string; + defaultPort: string; + elasticsearchUrl: string; + kibanaUrl: string; + } + | undefined { + // 1. Ignore anything before `:`. + const id = cid.split(':').pop(); + if (!id) { + // throw new Error(`Unable to decode ${id}`); + // eslint-disable-next-line no-console + console.debug(`Unable to decode ${id}`); + return; + } + + // 2. base64 decode + let decoded: string | undefined; + try { + decoded = Buffer.from(id, 'base64').toString('utf8'); + } catch { + // throw new Error(`base64 decoding failed on ${id}`); + // eslint-disable-next-line no-console + console.debug(`base64 decoding failed on ${id}`); + return; + } + + // 3. separate based on `$` + const words = decoded.split('$'); + if (words.length < 3) { + // throw new Error(`Expected at least 3 parts in ${decoded}`); + // eslint-disable-next-line no-console + console.debug(`Expected at least 3 parts in ${decoded}`); + return; + } + // 4. extract port from the ES and Kibana host + const [host, defaultPort] = extractPortFromName(words[0]); + const [esId, esPort] = extractPortFromName(words[1], defaultPort); + const [kbId, kbPort] = extractPortFromName(words[2], defaultPort); + // 5. form the URLs + const esUrl = `https://${esId}.${host}:${esPort}`; + const kbUrl = `https://${kbId}.${host}:${kbPort}`; + return { + host, + defaultPort, + elasticsearchUrl: esUrl, + kibanaUrl: kbUrl, + }; +} +// extractPortFromName takes a string in the form `id:port` and returns the +// Id and the port. If there's no `:`, the default port is returned +function extractPortFromName(word: string, defaultPort = '443') { + const [host, port = defaultPort] = word.split(':'); + return [host, port]; +} diff --git a/x-pack/plugins/ingest_manager/common/services/index.ts b/x-pack/plugins/ingest_manager/common/services/index.ts index 8e704bb717257..91dbbdd515c3e 100644 --- a/x-pack/plugins/ingest_manager/common/services/index.ts +++ b/x-pack/plugins/ingest_manager/common/services/index.ts @@ -9,3 +9,4 @@ export * from './routes'; export { packageToConfigDatasourceInputs, packageToConfigDatasource } from './package_to_config'; export { storedDatasourceToAgentDatasource } from './datasource_to_agent_datasource'; export { AgentStatusKueryHelper }; +export { decodeCloudId } from './decode_cloud_id'; diff --git a/x-pack/plugins/ingest_manager/common/types/index.ts b/x-pack/plugins/ingest_manager/common/types/index.ts index b357d0c2d75f4..800e77a6a2742 100644 --- a/x-pack/plugins/ingest_manager/common/types/index.ts +++ b/x-pack/plugins/ingest_manager/common/types/index.ts @@ -15,7 +15,6 @@ export interface IngestManagerConfigType { fleet: { enabled: boolean; tlsCheckDisabled: boolean; - defaultOutputHost: string; kibana: { host?: string; ca_sha256?: string; diff --git a/x-pack/plugins/ingest_manager/server/index.ts b/x-pack/plugins/ingest_manager/server/index.ts index 6096af8d80801..84408b60d3edb 100644 --- a/x-pack/plugins/ingest_manager/server/index.ts +++ b/x-pack/plugins/ingest_manager/server/index.ts @@ -32,7 +32,7 @@ export const config = { ca_sha256: schema.maybe(schema.string()), }), elasticsearch: schema.object({ - host: schema.string({ defaultValue: 'http://localhost:9200' }), + host: schema.maybe(schema.string()), ca_sha256: schema.maybe(schema.string()), }), }), diff --git a/x-pack/plugins/ingest_manager/server/services/output.ts b/x-pack/plugins/ingest_manager/server/services/output.ts index 3628c5bd9e183..ce6f1f2e27130 100644 --- a/x-pack/plugins/ingest_manager/server/services/output.ts +++ b/x-pack/plugins/ingest_manager/server/services/output.ts @@ -7,6 +7,7 @@ import { SavedObjectsClientContract } from 'src/core/server'; import { NewOutput, Output } from '../types'; import { DEFAULT_OUTPUT, OUTPUT_SAVED_OBJECT_TYPE } from '../constants'; import { appContextService } from './app_context'; +import { decodeCloudId } from '../../common'; const SAVED_OBJECT_TYPE = OUTPUT_SAVED_OBJECT_TYPE; @@ -16,11 +17,17 @@ class OutputService { type: OUTPUT_SAVED_OBJECT_TYPE, filter: `${OUTPUT_SAVED_OBJECT_TYPE}.attributes.is_default:true`, }); + const cloud = appContextService.getCloud(); + const cloudId = cloud?.isCloudEnabled && cloud.cloudId; + const cloudUrl = cloudId && decodeCloudId(cloudId)?.elasticsearchUrl; + const flagsUrl = appContextService.getConfig()!.fleet.elasticsearch.host; + const defaultUrl = 'http://localhost:9200'; + const defaultOutputUrl = cloudUrl || flagsUrl || defaultUrl; if (!outputs.saved_objects.length) { const newDefaultOutput = { ...DEFAULT_OUTPUT, - hosts: [appContextService.getConfig()!.fleet.elasticsearch.host], + hosts: [defaultOutputUrl], ca_sha256: appContextService.getConfig()!.fleet.elasticsearch.ca_sha256, } as NewOutput; diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/ingest_manager/server/services/setup.ts index 22acce8d4a51c..14837d9edd1cc 100644 --- a/x-pack/plugins/ingest_manager/server/services/setup.ts +++ b/x-pack/plugins/ingest_manager/server/services/setup.ts @@ -18,6 +18,7 @@ import { Installation, Output, DEFAULT_AGENT_CONFIGS_PACKAGES, + decodeCloudId, } from '../../common'; import { getPackageInfo } from './epm/packages'; import { datasourceService } from './datasource'; @@ -43,7 +44,11 @@ export async function setupIngestManager( const serverInfo = http.getServerInfo(); const basePath = http.basePath; - const defaultKibanaUrl = url.format({ + const cloud = appContextService.getCloud(); + const cloudId = cloud?.isCloudEnabled && cloud.cloudId; + const cloudUrl = cloudId && decodeCloudId(cloudId)?.kibanaUrl; + const flagsUrl = appContextService.getConfig()?.fleet?.kibana?.host; + const defaultUrl = url.format({ protocol: serverInfo.protocol, hostname: serverInfo.host, port: serverInfo.port, @@ -53,7 +58,7 @@ export async function setupIngestManager( return settingsService.saveSettings(soClient, { agent_auto_upgrade: true, package_auto_upgrade: true, - kibana_url: appContextService.getConfig()?.fleet?.kibana?.host ?? defaultKibanaUrl, + kibana_url: cloudUrl || flagsUrl || defaultUrl, }); } From 65ab0c6b3568beb9324309930cc345610fb1c1a2 Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 5 May 2020 16:03:45 -0700 Subject: [PATCH 48/72] [interpreter] remove unused code (#65332) --- .../tasks/build/server_code_transformer.js | 43 ----------------- .../build/server_code_transformer.test.js | 48 ------------------- 2 files changed, 91 deletions(-) delete mode 100644 packages/kbn-interpreter/tasks/build/server_code_transformer.js delete mode 100644 packages/kbn-interpreter/tasks/build/server_code_transformer.test.js diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.js deleted file mode 100644 index 4bd9220993c62..0000000000000 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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. - */ - -const { extname } = require('path'); - -const { transform } = require('@babel/core'); - -exports.createServerCodeTransformer = sourceMaps => { - return (content, path) => { - switch (extname(path)) { - case '.js': - const { code = '' } = transform(content.toString('utf8'), { - filename: path, - ast: false, - code: true, - sourceMaps: sourceMaps ? 'inline' : false, - babelrc: false, - presets: [require.resolve('@kbn/babel-preset/webpack_preset')], - }); - - return code; - - default: - return content.toString('utf8'); - } - }; -}; diff --git a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js b/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js deleted file mode 100644 index 519e529c20bf5..0000000000000 --- a/packages/kbn-interpreter/tasks/build/server_code_transformer.test.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 { readFileSync } from 'fs'; -import { resolve } from 'path'; -import { createServerCodeTransformer } from './server_code_transformer'; - -const JS_FIXTURE_PATH = resolve(__dirname, '__fixtures__/sample.js'); -const JS_FIXTURE = readFileSync(JS_FIXTURE_PATH); - -describe('js support', () => { - it('transpiles js file', () => { - const transformer = createServerCodeTransformer(); - expect(transformer(JS_FIXTURE, JS_FIXTURE_PATH)).toMatchInlineSnapshot(` -"\\"use strict\\"; - -var _util = _interopRequireDefault(require(\\"util\\")); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* eslint-disable */ -console.log(_util.default.format('hello world'));" -`); - }); - - it('throws errors for js syntax errors', () => { - const transformer = createServerCodeTransformer(); - expect(() => transformer(Buffer.from(`export default 'foo`), JS_FIXTURE_PATH)).toThrowError( - /Unterminated string constant/ - ); - }); -}); From 65447ec62fbff5edcffc761fa596f9be1f78057d Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Tue, 5 May 2020 16:02:26 -0700 Subject: [PATCH 49/72] [test] Skip ML test preventing promotion of ES snapshot "machine learning anomaly detection single metric job cloning displays the summary step" https://github.com/elastic/kibana/issues/65377 Signed-off-by: Tyler Smalley --- .../machine_learning/anomaly_detection/single_metric_job.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index 0f8655e3c6bbc..913b0e71f6a3e 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -325,7 +325,8 @@ export default function({ getService }: FtrProviderContext) { await ml.jobWizardCommon.advanceToValidationSection(); }); - it('job cloning displays the summary step', async () => { + // https://github.com/elastic/kibana/issues/65377 + it.skip('job cloning displays the summary step', async () => { await ml.jobWizardCommon.advanceToSummarySection(); }); From dc647a6e4ce4ed1ca6e6f81318dadee5b65b899a Mon Sep 17 00:00:00 2001 From: Spencer Date: Tue, 5 May 2020 16:13:48 -0700 Subject: [PATCH 50/72] [pre-commit script] refactor for speed (#65202) --- .../kbn-dev-utils/src/precommit_hook/cli.ts | 50 ++++++ .../src/precommit_hook/get_git_dir.ts | 14 +- .../src/precommit_hook/script_source.ts | 117 ++++++++++++ scripts/register_git_hook.js | 4 +- .../register_git_hook/register_git_hook.js | 169 ------------------ src/setup_node_env/index.js | 9 +- .../prebuilt_dev_only_entry.js} | 16 +- 7 files changed, 190 insertions(+), 189 deletions(-) create mode 100644 packages/kbn-dev-utils/src/precommit_hook/cli.ts rename src/dev/register_git_hook/index.js => packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts (70%) create mode 100644 packages/kbn-dev-utils/src/precommit_hook/script_source.ts delete mode 100644 src/dev/register_git_hook/register_git_hook.js rename src/{dev/run_register_git_hook.js => setup_node_env/prebuilt_dev_only_entry.js} (73%) diff --git a/packages/kbn-dev-utils/src/precommit_hook/cli.ts b/packages/kbn-dev-utils/src/precommit_hook/cli.ts new file mode 100644 index 0000000000000..a83e8c2b193d9 --- /dev/null +++ b/packages/kbn-dev-utils/src/precommit_hook/cli.ts @@ -0,0 +1,50 @@ +/* + * 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 Path from 'path'; +import { chmod, writeFile } from 'fs'; +import { promisify } from 'util'; + +import { run } from '../run'; +import { REPO_ROOT } from '../repo_root'; +import { SCRIPT_SOURCE } from './script_source'; +import { getGitDir } from './get_git_dir'; + +const chmodAsync = promisify(chmod); +const writeFileAsync = promisify(writeFile); + +run( + async ({ log }) => { + try { + const gitDir = await getGitDir(); + const installPath = Path.resolve(REPO_ROOT, gitDir, 'hooks/pre-commit'); + + log.info(`Registering Kibana pre-commit git hook...`); + await writeFileAsync(installPath, SCRIPT_SOURCE); + await chmodAsync(installPath, 0o755); + log.success(`Kibana pre-commit git hook was installed successfully.`); + } catch (e) { + log.error(`Kibana pre-commit git hook was not installed as an error occur.`); + throw e; + } + }, + { + description: 'Register git hooks in the local repo', + } +); diff --git a/src/dev/register_git_hook/index.js b/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts similarity index 70% rename from src/dev/register_git_hook/index.js rename to packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts index 6089256423ff6..5ca7d67d0d4ea 100644 --- a/src/dev/register_git_hook/index.js +++ b/packages/kbn-dev-utils/src/precommit_hook/get_git_dir.ts @@ -17,4 +17,16 @@ * under the License. */ -export { registerPrecommitGitHook } from './register_git_hook'; +import execa from 'execa'; + +import { REPO_ROOT } from '../repo_root'; + +// Retrieves the correct location for the .git dir for +// every git setup (including git worktree) +export async function getGitDir() { + return ( + await execa('git', ['rev-parse', '--git-common-dir'], { + cwd: REPO_ROOT, + }) + ).stdout.trim(); +} diff --git a/packages/kbn-dev-utils/src/precommit_hook/script_source.ts b/packages/kbn-dev-utils/src/precommit_hook/script_source.ts new file mode 100644 index 0000000000000..61b4552f6eaef --- /dev/null +++ b/packages/kbn-dev-utils/src/precommit_hook/script_source.ts @@ -0,0 +1,117 @@ +/* + * 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 os from 'os'; + +import normalizePath from 'normalize-path'; + +const HOME_DIR = normalizePath(os.homedir()); + +export const SCRIPT_SOURCE = `#!/usr/bin/env bash +# +# ** THIS IS AN AUTO-GENERATED FILE ** +# ** PLEASE DO NOT CHANGE IT MANUALLY ** +# +# GENERATED BY \`node scripts/register_git_hook\` +# IF YOU WANNA CHANGE SOMETHING IN THIS SCRIPT +# PLEASE RE-RUN 'yarn kbn bootstrap' or 'node scripts/register_git_hook' + +# pre-commit script takes zero arguments: https://git-scm.com/docs/githooks#_pre_commit + +set -euo pipefail + +# Make it possible to terminate pre commit hook +# using ctrl-c so nothing else would happen or be +# sent to the output. +# +# The correct exit code on that situation +# according the linux documentation project is 130 +# https://www.tldp.org/LDP/abs/html/exitcodes.html +trap "exit 130" INT + +has_node() { + command -v node >/dev/null 2>&1 +} + +has_nvm() { + command -v nvm >/dev/null 2>&1 +} + +try_load_node_from_nvm_paths () { + # If nvm is not loaded, load it + has_node || { + NVM_SH="${HOME_DIR}/.nvm/nvm.sh" + + if [ "${process.platform}" == "darwin" ] && [ -s "$(brew --prefix nvm)/nvm.sh" ]; then + NVM_SH="$(brew --prefix nvm)/nvm.sh" + fi + + export NVM_DIR="${HOME_DIR}/.nvm" + + [ -s "$NVM_SH" ] && \. "$NVM_SH" + + # If nvm has been loaded correctly, use project .nvmrc + has_nvm && nvm use + } +} + +extend_user_path() { + if [ "${process.platform}" == "win32" ]; then + export PATH="$PATH:/c/Program Files/nodejs" + else + export PATH="$PATH:/usr/local/bin:/usr/local" + try_load_node_from_nvm_paths + fi +} + +# Extend path with common path locations for node +# in order to make the hook working on git GUI apps +extend_user_path + +# Check if we have node js bin in path +has_node || { + echo "Can't found node bin in the PATH. Please update the PATH to proceed." + echo "If your PATH already has the node bin, maybe you are using some git GUI app." + echo "Can't found node bin in the PATH. Please update the PATH to proceed." + echo "If your PATH already has the node bin, maybe you are using some git GUI app not launched from the shell." + echo "In order to proceed, you need to config the PATH used by the application that are launching your git GUI app." + echo "If you are running macOS, you can do that using:" + echo "'sudo launchctl config user path /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'" + + exit 1 +} + +execute_precommit_hook() { + node scripts/precommit_hook || return 1 + + PRECOMMIT_FILE="./.git/hooks/pre-commit.local" + if [ -x "\${PRECOMMIT_FILE}" ]; then + echo "Executing local precommit hook found in \${PRECOMMIT_FILE}" + "$PRECOMMIT_FILE" || return 1 + fi +} + +execute_precommit_hook || { + echo "Pre-commit hook failed (add --no-verify to bypass)"; + echo ' For eslint failures you can try running \`node scripts/precommit_hook --fix\`'; + exit 1; +} + +exit 0 +`; diff --git a/scripts/register_git_hook.js b/scripts/register_git_hook.js index 8e03f17967f3f..af3f54619bcec 100644 --- a/scripts/register_git_hook.js +++ b/scripts/register_git_hook.js @@ -17,5 +17,5 @@ * under the License. */ -require('../src/setup_node_env'); -require('../src/dev/run_register_git_hook'); +require('../src/setup_node_env/prebuilt_dev_only_entry'); +require('@kbn/dev-utils/target/precommit_hook/cli'); diff --git a/src/dev/register_git_hook/register_git_hook.js b/src/dev/register_git_hook/register_git_hook.js deleted file mode 100644 index 8820327d3adc0..0000000000000 --- a/src/dev/register_git_hook/register_git_hook.js +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 chalk from 'chalk'; -import { chmod, unlink, writeFile } from 'fs'; -import dedent from 'dedent'; -import normalizePath from 'normalize-path'; -import os from 'os'; -import { resolve } from 'path'; -import { promisify } from 'util'; -import SimpleGit from 'simple-git'; -import { REPO_ROOT } from '../constants'; - -const simpleGit = new SimpleGit(REPO_ROOT); - -const chmodAsync = promisify(chmod); -const gitRevParseAsync = promisify(simpleGit.revparse.bind(simpleGit)); -const unlinkAsync = promisify(unlink); -const writeFileAsync = promisify(writeFile); - -async function getPrecommitGitHookScriptPath(rootPath) { - // Retrieves the correct location for the .git dir for - // every git setup (including git worktree) - const gitDirPath = (await gitRevParseAsync(['--git-common-dir'])).trim(); - - return resolve(rootPath, gitDirPath, 'hooks/pre-commit'); -} - -function getKbnPrecommitGitHookScript(rootPath, nodeHome, platform) { - return dedent(` - #!/usr/bin/env bash - # - # ** THIS IS AN AUTO-GENERATED FILE ** - # ** PLEASE DO NOT CHANGE IT MANUALLY ** - # - # GENERATED BY ${__dirname} - # IF YOU WANNA CHANGE SOMETHING INTO THIS SCRIPT - # PLEASE RE-RUN 'yarn kbn bootstrap' or 'node scripts/register_git_hook' IN THE ROOT - # OF THE CURRENT PROJECT ${rootPath} - - # pre-commit script takes zero arguments: https://git-scm.com/docs/githooks#_pre_commit - - set -euo pipefail - - # Make it possible to terminate pre commit hook - # using ctrl-c so nothing else would happen or be - # sent to the output. - # - # The correct exit code on that situation - # according the linux documentation project is 130 - # https://www.tldp.org/LDP/abs/html/exitcodes.html - trap "exit 130" INT - - has_node() { - command -v node >/dev/null 2>&1 - } - - has_nvm() { - command -v nvm >/dev/null 2>&1 - } - - try_load_node_from_nvm_paths () { - # If nvm is not loaded, load it - has_node || { - NVM_SH="${nodeHome}/.nvm/nvm.sh" - - if [ "${platform}" == "darwin" ] && [ -s "$(brew --prefix nvm)/nvm.sh" ]; then - NVM_SH="$(brew --prefix nvm)/nvm.sh" - fi - - export NVM_DIR=${nodeHome}/.nvm - - [ -s "$NVM_SH" ] && \. "$NVM_SH" - - # If nvm has been loaded correctly, use project .nvmrc - has_nvm && nvm use - } - } - - extend_user_path() { - if [ "${platform}" == "win32" ]; then - export PATH="$PATH:/c/Program Files/nodejs" - else - export PATH="$PATH:/usr/local/bin:/usr/local" - try_load_node_from_nvm_paths - fi - } - - # Extend path with common path locations for node - # in order to make the hook working on git GUI apps - extend_user_path - - # Check if we have node js bin in path - has_node || { - echo "Can't found node bin in the PATH. Please update the PATH to proceed." - echo "If your PATH already has the node bin, maybe you are using some git GUI app." - echo "Can't found node bin in the PATH. Please update the PATH to proceed." - echo "If your PATH already has the node bin, maybe you are using some git GUI app not launched from the shell." - echo "In order to proceed, you need to config the PATH used by the application that are launching your git GUI app." - echo "If you are running macOS, you can do that using:" - echo "'sudo launchctl config user path /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'" - - exit 1 - } - - execute_precommit_hook() { - node scripts/precommit_hook || return 1 - - PRECOMMIT_FILE="./.git/hooks/pre-commit.local" - if [ -x "\${PRECOMMIT_FILE}" ]; then - echo "Executing local precommit hook found in \${PRECOMMIT_FILE}" - "$PRECOMMIT_FILE" || return 1 - fi - } - - execute_precommit_hook || { - echo "Pre-commit hook failed (add --no-verify to bypass)"; - echo ' For eslint failures you can try running \`node scripts/precommit_hook --fix\`'; - exit 1; - } - - exit 0 - `); -} - -export async function registerPrecommitGitHook(log) { - log.write(chalk.bold(`Registering Kibana pre-commit git hook...\n`)); - - try { - await writeGitHook( - await getPrecommitGitHookScriptPath(REPO_ROOT), - getKbnPrecommitGitHookScript(REPO_ROOT, normalizePath(os.homedir()), process.platform) - ); - } catch (e) { - log.write( - `${chalk.red('fail')} Kibana pre-commit git hook was not installed as an error occur.\n` - ); - throw e; - } - - log.write(`${chalk.green('success')} Kibana pre-commit git hook was installed successfully.\n`); -} - -async function writeGitHook(gitHookScriptPath, kbnHookScriptSource) { - try { - await unlinkAsync(gitHookScriptPath); - } catch (e) { - /* no-op */ - } - - await writeFileAsync(gitHookScriptPath, kbnHookScriptSource); - await chmodAsync(gitHookScriptPath, 0o755); -} diff --git a/src/setup_node_env/index.js b/src/setup_node_env/index.js index 97de5ba76b926..d84249df7fd8f 100644 --- a/src/setup_node_env/index.js +++ b/src/setup_node_env/index.js @@ -17,12 +17,5 @@ * under the License. */ -// The following require statements MUST be executed before any others - BEGIN -require('./exit_on_warning'); -require('./harden'); -// The following require statements MUST be executed before any others - END - -require('symbol-observable'); -require('./root'); -require('./node_version_validator'); +require('./prebuilt_dev_only_entry'); require('./babel_register'); diff --git a/src/dev/run_register_git_hook.js b/src/setup_node_env/prebuilt_dev_only_entry.js similarity index 73% rename from src/dev/run_register_git_hook.js rename to src/setup_node_env/prebuilt_dev_only_entry.js index 8d5bb9e59359b..9453b3bd67eb7 100644 --- a/src/dev/run_register_git_hook.js +++ b/src/setup_node_env/prebuilt_dev_only_entry.js @@ -17,13 +17,11 @@ * under the License. */ -import { run, createFailError } from '@kbn/dev-utils'; -import { registerPrecommitGitHook } from './register_git_hook'; +// The following require statements MUST be executed before any others - BEGIN +require('./exit_on_warning'); +require('./harden'); +// The following require statements MUST be executed before any others - END -run(async ({ log }) => { - try { - await registerPrecommitGitHook(log); - } catch (error) { - throw createFailError(error); - } -}); +require('symbol-observable'); +require('./root'); +require('./node_version_validator'); From a1f8ad039e2e3b18a0248d9457b9e0f1e22df87f Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 29 Apr 2020 12:53:06 -0700 Subject: [PATCH 51/72] skip flaky suite (#64812) (#64723) --- .../test_suites/event_log/public_api_integration.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts index a2ae165986340..f5cc1cc166ee8 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts @@ -19,7 +19,9 @@ export default function({ getService }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); - describe('Event Log public API', () => { + // FLAKY: https://github.com/elastic/kibana/issues/64723 + // FLAKY: https://github.com/elastic/kibana/issues/64812 + describe.skip('Event Log public API', () => { it('should allow querying for events by Saved Object', async () => { const id = uuid.v4(); From daceebb329aadd2e74c77a8ab26339ce1b551e76 Mon Sep 17 00:00:00 2001 From: Sandra Gonzales Date: Tue, 5 May 2020 19:36:47 -0400 Subject: [PATCH 52/72] [Ingest] check and create default indices during setup (#64809) * check and create default indices during setup * fix typos * add kibana issue * add date mapping * add removeDocValues to each field to stop apps from creating a new index pattern * update snapshot * add property to test data --- .../ingest_manager/common/constants/epm.ts | 1 + .../ingest_manager/server/constants/index.ts | 1 + .../__snapshots__/install.test.ts.snap | 88 ++++++++++++++----- .../epm/kibana/index_pattern/install.ts | 51 ++++++++++- .../kibana/index_pattern/tests/test_data.ts | 8 ++ .../ingest_manager/server/services/setup.ts | 2 + 6 files changed, 128 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/ingest_manager/common/constants/epm.ts b/x-pack/plugins/ingest_manager/common/constants/epm.ts index 4fb259609493d..97b5cca369298 100644 --- a/x-pack/plugins/ingest_manager/common/constants/epm.ts +++ b/x-pack/plugins/ingest_manager/common/constants/epm.ts @@ -7,3 +7,4 @@ export const PACKAGES_SAVED_OBJECT_TYPE = 'epm-packages'; export const INDEX_PATTERN_SAVED_OBJECT_TYPE = 'index-pattern'; export const DEFAULT_REGISTRY_URL = 'https://epr.elastic.co'; +export const INDEX_PATTERN_PLACEHOLDER_SUFFIX = '-index_pattern_placeholder'; diff --git a/x-pack/plugins/ingest_manager/server/constants/index.ts b/x-pack/plugins/ingest_manager/server/constants/index.ts index 3468c56cc877f..6e633c04ed816 100644 --- a/x-pack/plugins/ingest_manager/server/constants/index.ts +++ b/x-pack/plugins/ingest_manager/server/constants/index.ts @@ -9,6 +9,7 @@ export { AGENT_TYPE_TEMPORARY, AGENT_POLLING_THRESHOLD_MS, AGENT_POLLING_INTERVAL, + INDEX_PATTERN_PLACEHOLDER_SUFFIX, // Routes PLUGIN_ID, EPM_API_ROUTES, diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap index d063ebe92f938..029e278b5aa93 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/__snapshots__/install.test.ts.snap @@ -40,7 +40,7 @@ exports[`creating index patterns from yaml fields createIndexPattern function cr { "title": "logs-*", "timeFieldName": "@timestamp", - "fields": "[{\\"name\\":\\"coredns.id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.allParams\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.length\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.size\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.class\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.query.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.query.type\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.flags\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.size\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.dnssec_ok\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"boolean\\"},{\\"name\\":\\"@timestamp\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"date\\"},{\\"name\\":\\"labels\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"message\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"tags\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.ephemeral_id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.type\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.version\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"as.number\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"as.organization.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"nginx.access.remote_ip_list\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.body_sent.bytes\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.method\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.url\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.http_version\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.response_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.referrer\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.agent\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_agent.device\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_agent.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_agent.os\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_agent.os_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.user_agent.original\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.geoip.continent_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"nginx.access.geoip.country_iso_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.geoip.location\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.geoip.region_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.geoip.city_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"nginx.access.geoip.region_iso_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true},{\\"name\\":\\"source.geo.continent_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country.keyword\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country.text\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"type\\":\\"string\\"}]", + "fields": "[{\\"name\\":\\"coredns.id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.allParams\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.length\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.size\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.query.class\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.query.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.query.type\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.flags\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"coredns.response.size\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"coredns.dnssec_ok\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"boolean\\"},{\\"name\\":\\"@timestamp\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"date\\"},{\\"name\\":\\"labels\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"message\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"tags\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.ephemeral_id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.id\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.type\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"agent.version\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"as.number\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"number\\"},{\\"name\\":\\"as.organization.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"nginx.access.remote_ip_list\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.body_sent.bytes\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.method\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.url\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.http_version\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.response_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.referrer\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.agent\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_agent.device\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_agent.name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_agent.os\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_agent.os_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.user_agent.original\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.geoip.continent_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"nginx.access.geoip.country_iso_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.geoip.location\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.geoip.region_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.geoip.city_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"nginx.access.geoip.region_iso_code\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true},{\\"name\\":\\"source.geo.continent_name\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country.keyword\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":true,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"},{\\"name\\":\\"country.text\\",\\"count\\":0,\\"scripted\\":false,\\"indexed\\":true,\\"analyzed\\":false,\\"searchable\\":true,\\"aggregatable\\":false,\\"doc_values\\":true,\\"readFromDocValues\\":true,\\"type\\":\\"string\\"}]", "fieldFormatMap": "{\\"coredns.allParams\\":{\\"id\\":\\"bytes\\",\\"params\\":{\\"pattern\\":\\"patternValQueryWeight\\",\\"inputFormat\\":\\"inputFormatVal,\\",\\"outputFormat\\":\\"outputFormalVal,\\",\\"outputPrecision\\":\\"3,\\",\\"labelTemplate\\":\\"labelTemplateVal,\\",\\"urlTemplate\\":\\"urlTemplateVal,\\"}},\\"coredns.query.length\\":{\\"params\\":{\\"pattern\\":\\"patternValQueryLength\\"}},\\"coredns.query.size\\":{\\"id\\":\\"bytes\\",\\"params\\":{\\"pattern\\":\\"patternValQuerySize\\"}},\\"coredns.response.size\\":{\\"id\\":\\"bytes\\"}}" } `; @@ -57,6 +57,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -68,6 +69,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "number" }, { @@ -79,6 +81,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "number" }, { @@ -90,6 +93,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "number" }, { @@ -101,6 +105,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -112,6 +117,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -123,6 +129,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -134,6 +141,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -145,6 +153,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -156,6 +165,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "number" }, { @@ -167,6 +177,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "boolean" }, { @@ -178,6 +189,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "date" }, { @@ -188,7 +200,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "message", @@ -199,6 +212,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": false, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -210,6 +224,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -221,6 +236,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -232,6 +248,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -243,6 +260,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -254,6 +272,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -265,6 +284,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -276,6 +296,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "number" }, { @@ -287,6 +308,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -297,7 +319,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.body_sent.bytes", @@ -307,7 +330,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_name", @@ -317,7 +341,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.method", @@ -327,7 +352,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.url", @@ -337,7 +363,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.http_version", @@ -347,7 +374,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.response_code", @@ -357,7 +385,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.referrer", @@ -367,7 +396,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.agent", @@ -377,7 +407,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_agent.device", @@ -387,7 +418,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_agent.name", @@ -397,7 +429,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_agent.os", @@ -407,7 +440,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_agent.os_name", @@ -417,7 +451,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.user_agent.original", @@ -427,7 +462,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.geoip.continent_name", @@ -438,6 +474,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": false, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -448,7 +485,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.geoip.location", @@ -458,7 +496,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.geoip.region_name", @@ -468,7 +507,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.geoip.city_name", @@ -478,7 +518,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "nginx.access.geoip.region_iso_code", @@ -488,7 +529,8 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "analyzed": false, "searchable": true, "aggregatable": true, - "doc_values": true + "doc_values": true, + "readFromDocValues": true }, { "name": "source.geo.continent_name", @@ -499,6 +541,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": false, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -510,6 +553,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -521,6 +565,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": true, "doc_values": true, + "readFromDocValues": true, "type": "string" }, { @@ -532,6 +577,7 @@ exports[`creating index patterns from yaml fields createIndexPatternFields funct "searchable": true, "aggregatable": false, "doc_values": true, + "readFromDocValues": true, "type": "string" } ], diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts index ec657820a2225..f6db5dfe353ea 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/install.ts @@ -5,11 +5,14 @@ */ import { SavedObjectsClientContract } from 'src/core/server'; -import { INDEX_PATTERN_SAVED_OBJECT_TYPE } from '../../../../constants'; +import { + INDEX_PATTERN_SAVED_OBJECT_TYPE, + INDEX_PATTERN_PLACEHOLDER_SUFFIX, +} from '../../../../constants'; import * as Registry from '../../registry'; import { loadFieldsFromYaml, Fields, Field } from '../../fields/field'; import { getPackageKeysByStatus } from '../../packages/get'; -import { InstallationStatus, RegistryPackage } from '../../../../types'; +import { InstallationStatus, RegistryPackage, CallESAsCurrentUser } from '../../../../types'; interface FieldFormatMap { [key: string]: FieldFormatMapItem; @@ -63,6 +66,7 @@ export interface IndexPatternField { enabled?: boolean; script?: string; lang?: string; + readFromDocValues: boolean; } export enum IndexPatternType { logs = 'logs', @@ -234,6 +238,7 @@ export const transformField = (field: Field, i: number, fields: Fields): IndexPa searchable: field.searchable ?? true, aggregatable: field.aggregatable ?? true, doc_values: field.doc_values ?? true, + readFromDocValues: field.doc_values ?? true, }; // if type exists, check if it exists in the map @@ -251,6 +256,7 @@ export const transformField = (field: Field, i: number, fields: Fields): IndexPa newField.aggregatable = false; newField.analyzed = false; newField.doc_values = field.doc_values ?? false; + newField.readFromDocValues = field.doc_values ?? false; newField.indexed = false; newField.searchable = false; } @@ -262,6 +268,7 @@ export const transformField = (field: Field, i: number, fields: Fields): IndexPa newField.aggregatable = false; newField.analyzed = false; newField.doc_values = false; + newField.readFromDocValues = false; newField.indexed = false; newField.searchable = false; } @@ -276,6 +283,7 @@ export const transformField = (field: Field, i: number, fields: Fields): IndexPa newField.script = field.script; newField.lang = 'painless'; newField.doc_values = false; + newField.readFromDocValues = false; } return newField; @@ -357,3 +365,42 @@ const getFieldFormatParams = (field: Field): FieldFormatParams => { if (field.open_link_in_current_tab) params.openLinkInCurrentTab = field.open_link_in_current_tab; return params; }; + +export const ensureDefaultIndices = async (callCluster: CallESAsCurrentUser) => + // create placeholder indices to supress errors in the kibana Dashboards app + // that no matching indices exist https://github.com/elastic/kibana/issues/62343 + Promise.all( + Object.keys(IndexPatternType).map(async indexPattern => { + const defaultIndexPatternName = indexPattern + INDEX_PATTERN_PLACEHOLDER_SUFFIX; + const indexExists = await doesIndexExist(defaultIndexPatternName, callCluster); + if (!indexExists) { + try { + await callCluster('transport.request', { + method: 'PUT', + path: `/${defaultIndexPatternName}`, + body: { + mappings: { + properties: { + '@timestamp': { type: 'date' }, + }, + }, + }, + }); + } catch (putErr) { + throw new Error(`${defaultIndexPatternName} could not be created`); + } + } + }) + ); + +export const doesIndexExist = async (indexName: string, callCluster: CallESAsCurrentUser) => { + try { + await callCluster('transport.request', { + method: 'HEAD', + path: indexName, + }); + return true; + } catch (err) { + return false; + } +}; diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts index 13bef1b6ddb2c..879db91bfacaa 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/index_pattern/tests/test_data.ts @@ -15,6 +15,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -26,6 +27,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -37,6 +39,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -48,6 +51,7 @@ export const dupeFields: IndexPatternField[] = [ count: 2, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -59,6 +63,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -70,6 +75,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -81,6 +87,7 @@ export const dupeFields: IndexPatternField[] = [ count: 0, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: true, }, @@ -92,6 +99,7 @@ export const dupeFields: IndexPatternField[] = [ count: 1, indexed: true, doc_values: true, + readFromDocValues: true, scripted: false, analyzed: false, }, diff --git a/x-pack/plugins/ingest_manager/server/services/setup.ts b/x-pack/plugins/ingest_manager/server/services/setup.ts index 14837d9edd1cc..2861458fde9d7 100644 --- a/x-pack/plugins/ingest_manager/server/services/setup.ts +++ b/x-pack/plugins/ingest_manager/server/services/setup.ts @@ -11,6 +11,7 @@ import { CallESAsCurrentUser } from '../types'; import { agentConfigService } from './agent_config'; import { outputService } from './output'; import { ensureInstalledDefaultPackages } from './epm/packages/install'; +import { ensureDefaultIndices } from './epm/kibana/index_pattern/install'; import { packageToConfigDatasource, Datasource, @@ -38,6 +39,7 @@ export async function setupIngestManager( ensureInstalledDefaultPackages(soClient, callCluster), outputService.ensureDefaultOutput(soClient), agentConfigService.ensureDefaultAgentConfig(soClient), + ensureDefaultIndices(callCluster), settingsService.getSettings(soClient).catch((e: any) => { if (e.isBoom && e.output.statusCode === 404) { const http = appContextService.getHttpSetup(); From a5fe3ce92a26f3423f94f4c1c55e7528fd2bc871 Mon Sep 17 00:00:00 2001 From: Angela Chuang <6295984+angorayc@users.noreply.github.com> Date: Wed, 6 May 2020 01:05:12 +0100 Subject: [PATCH 53/72] [SIEM] template timeline UI (#64439) * init template timeline's tab * add template filter * add routes for timelines tabs * add tabs hook * add filter type * fix unit test * add breadcrumbs * fix types error * fix flashing table * fix types * fix flashing table * fix filter * add comments for filters * review X * review x * fix create note for template timeline * rename timelineTypes to timelineType * update unit test * fix types * update filter for timeline savedObject * fix lint error Co-authored-by: Elastic Machine Co-authored-by: Patryk Kopycinski Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> --- .../siem/public/components/link_to/index.ts | 6 +- .../public/components/link_to/link_to.tsx | 6 + .../link_to/redirect_to_timelines.tsx | 20 +- .../navigation/breadcrumbs/index.test.ts | 2 +- .../navigation/breadcrumbs/index.ts | 29 +- .../components/open_timeline/index.test.tsx | 57 ++- .../public/components/open_timeline/index.tsx | 44 +- .../open_timeline/open_timeline.test.tsx | 433 ++++-------------- .../open_timeline/open_timeline.tsx | 35 +- .../open_timeline_modal/index.test.tsx | 9 + .../open_timeline_modal_body.test.tsx | 223 +++------ .../open_timeline_modal_body.tsx | 22 +- .../open_timeline/search_row/index.tsx | 30 +- .../components/open_timeline/translations.ts | 14 + .../public/components/open_timeline/types.ts | 19 +- .../open_timeline/use_timeline_types.tsx | 106 +++++ .../components/recent_timelines/index.tsx | 9 +- .../timeline/selectable_timeline/index.tsx | 16 +- .../timeline/all/index.gql_query.ts | 2 + .../public/containers/timeline/all/index.tsx | 47 +- .../siem/public/graphql/introspection.json | 6 + x-pack/plugins/siem/public/graphql/types.ts | 3 + .../siem/public/pages/timelines/index.tsx | 61 ++- .../siem/public/store/timeline/model.ts | 2 +- .../plugins/siem/public/utils/route/types.ts | 8 +- .../siem/server/graphql/timeline/resolvers.ts | 3 +- .../server/graphql/timeline/schema.gql.ts | 2 +- x-pack/plugins/siem/server/graphql/types.ts | 4 + .../timeline/routes/import_timelines_route.ts | 31 +- .../timeline/routes/utils/import_timelines.ts | 11 +- .../siem/server/lib/timeline/saved_object.ts | 18 +- 31 files changed, 608 insertions(+), 670 deletions(-) create mode 100644 x-pack/plugins/siem/public/components/open_timeline/use_timeline_types.tsx diff --git a/x-pack/plugins/siem/public/components/link_to/index.ts b/x-pack/plugins/siem/public/components/link_to/index.ts index a1c1f78e398e3..c35a60766d7bd 100644 --- a/x-pack/plugins/siem/public/components/link_to/index.ts +++ b/x-pack/plugins/siem/public/components/link_to/index.ts @@ -12,7 +12,11 @@ export { export { getOverviewUrl, RedirectToOverviewPage } from './redirect_to_overview'; export { getHostDetailsUrl, getHostsUrl } from './redirect_to_hosts'; export { getNetworkUrl, getIPDetailsUrl, RedirectToNetworkPage } from './redirect_to_network'; -export { getTimelinesUrl, RedirectToTimelinesPage } from './redirect_to_timelines'; +export { + getTimelinesUrl, + getTimelineTabsUrl, + RedirectToTimelinesPage, +} from './redirect_to_timelines'; export { getCaseDetailsUrl, getCaseUrl, diff --git a/x-pack/plugins/siem/public/components/link_to/link_to.tsx b/x-pack/plugins/siem/public/components/link_to/link_to.tsx index 08e4d1a3494e0..d3bf2e34b435b 100644 --- a/x-pack/plugins/siem/public/components/link_to/link_to.tsx +++ b/x-pack/plugins/siem/public/components/link_to/link_to.tsx @@ -26,6 +26,7 @@ import { RedirectToConfigureCasesPage, } from './redirect_to_case'; import { DetectionEngineTab } from '../../pages/detection_engine/types'; +import { TimelineType } from '../../../common/types/timeline'; interface LinkToPageProps { match: RouteMatch<{}>; @@ -112,8 +113,13 @@ export const LinkToPage = React.memo(({ match }) => ( /> + )); diff --git a/x-pack/plugins/siem/public/components/link_to/redirect_to_timelines.tsx b/x-pack/plugins/siem/public/components/link_to/redirect_to_timelines.tsx index 27765a4125afc..9c704a7f70d29 100644 --- a/x-pack/plugins/siem/public/components/link_to/redirect_to_timelines.tsx +++ b/x-pack/plugins/siem/public/components/link_to/redirect_to_timelines.tsx @@ -11,14 +11,30 @@ import { SiemPageName } from '../../pages/home/types'; import { appendSearch } from './helpers'; import { RedirectWrapper } from './redirect_wrapper'; +import { TimelineTypeLiteral, TimelineType } from '../../../common/types/timeline'; export type TimelineComponentProps = RouteComponentProps<{ + tabName: TimelineTypeLiteral; search: string; }>; -export const RedirectToTimelinesPage = ({ location: { search } }: TimelineComponentProps) => ( - +export const RedirectToTimelinesPage = ({ + match: { + params: { tabName }, + }, + location: { search }, +}: TimelineComponentProps) => ( + ); export const getTimelinesUrl = (search?: string) => `#/link-to/${SiemPageName.timelines}${appendSearch(search)}`; + +export const getTimelineTabsUrl = (tabName: TimelineTypeLiteral, search?: string) => + `#/link-to/${SiemPageName.timelines}/${tabName}${appendSearch(search)}`; diff --git a/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.test.ts index 7770780fb9613..2acae92c390dd 100644 --- a/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.test.ts @@ -148,7 +148,7 @@ describe('Navigation Breadcrumbs', () => { ); expect(breadcrumbs).toEqual([ { text: 'SIEM', href: '#/link-to/overview' }, - { text: 'Timelines', href: '' }, + { text: 'Timelines', href: '#/link-to/timelines' }, ]); }); diff --git a/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.ts b/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.ts index 85d77485830a5..8abc099ee7f69 100644 --- a/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.ts +++ b/x-pack/plugins/siem/public/components/navigation/breadcrumbs/index.ts @@ -13,8 +13,14 @@ import { getBreadcrumbs as getHostDetailsBreadcrumbs } from '../../../pages/host import { getBreadcrumbs as getIPDetailsBreadcrumbs } from '../../../pages/network/ip_details'; import { getBreadcrumbs as getCaseDetailsBreadcrumbs } from '../../../pages/case/utils'; import { getBreadcrumbs as getDetectionRulesBreadcrumbs } from '../../../pages/detection_engine/rules/utils'; +import { getBreadcrumbs as getTimelinesBreadcrumbs } from '../../../pages/timelines'; import { SiemPageName } from '../../../pages/home/types'; -import { RouteSpyState, HostRouteSpyState, NetworkRouteSpyState } from '../../../utils/route/types'; +import { + RouteSpyState, + HostRouteSpyState, + NetworkRouteSpyState, + TimelineRouteSpyState, +} from '../../../utils/route/types'; import { getOverviewUrl } from '../../link_to'; import { TabNavigationProps } from '../tab_navigation/types'; @@ -44,6 +50,9 @@ const isNetworkRoutes = (spyState: RouteSpyState): spyState is NetworkRouteSpySt const isHostsRoutes = (spyState: RouteSpyState): spyState is HostRouteSpyState => spyState != null && spyState.pageName === SiemPageName.hosts; +const isTimelinesRoutes = (spyState: RouteSpyState): spyState is TimelineRouteSpyState => + spyState != null && spyState.pageName === SiemPageName.timelines; + const isCaseRoutes = (spyState: RouteSpyState): spyState is RouteSpyState => spyState != null && spyState.pageName === SiemPageName.case; @@ -124,6 +133,24 @@ export const getBreadcrumbsForRoute = ( ), ]; } + if (isTimelinesRoutes(spyState) && object.navTabs) { + const tempNav: SearchNavTab = { urlKey: 'timeline', isDetailPage: false }; + let urlStateKeys = [getOr(tempNav, spyState.pageName, object.navTabs)]; + if (spyState.tabName != null) { + urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; + } + + return [ + ...siemRootBreadcrumb, + ...getTimelinesBreadcrumbs( + spyState, + urlStateKeys.reduce( + (acc: string[], item: SearchNavTab) => [...acc, getSearch(item, object)], + [] + ) + ), + ]; + } if ( spyState != null && object.navTabs && diff --git a/x-pack/plugins/siem/public/components/open_timeline/index.test.tsx b/x-pack/plugins/siem/public/components/open_timeline/index.test.tsx index ea28bc06ef915..731c6d1ca9806 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/index.test.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/index.test.tsx @@ -17,16 +17,28 @@ import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines import { NotePreviews } from './note_previews'; import { OPEN_TIMELINE_CLASS_NAME } from './helpers'; +import { TimelineTabsStyle } from './types'; + import { StatefulOpenTimeline } from '.'; import { useGetAllTimeline, getAllTimeline } from '../../containers/timeline/all'; jest.mock('../../lib/kibana'); jest.mock('../../containers/timeline/all', () => { const originalModule = jest.requireActual('../../containers/timeline/all'); return { + ...originalModule, useGetAllTimeline: jest.fn(), getAllTimeline: originalModule.getAllTimeline, }; }); +jest.mock('./use_timeline_types', () => { + return { + useTimelineTypes: jest.fn().mockReturnValue({ + timelineType: 'default', + timelineTabs:
, + timelineFilters:
, + }), + }; +}); describe('StatefulOpenTimeline', () => { const theme = () => ({ eui: euiDarkVars, darkMode: true }); @@ -489,33 +501,30 @@ describe('StatefulOpenTimeline', () => { .text() ).toEqual('elastic'); }); - }); - test('it renders the title', async () => { - const wrapper = mount( - - - - - - - - ); + test('it renders the title', async () => { + const wrapper = mount( + + + + + + + + ); - await wait(); + await wait(); - expect( - wrapper - .find('[data-test-subj="header-section-title"]') - .first() - .text() - ).toEqual(title); + expect(wrapper.find(`[data-test-subj="timeline-${TimelineTabsStyle.tab}"]`).exists()).toEqual( + true + ); + }); }); describe('#resetSelectionState', () => { diff --git a/x-pack/plugins/siem/public/components/open_timeline/index.tsx b/x-pack/plugins/siem/public/components/open_timeline/index.tsx index d26d02780ffba..ed22673f07a78 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/index.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/index.tsx @@ -9,6 +9,7 @@ import React, { useEffect, useState, useCallback } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; + import { defaultHeaders } from '../../components/timeline/body/column_headers/default_headers'; import { deleteTimelineMutation } from '../../containers/timeline/delete/persist.gql_query'; import { useGetAllTimeline } from '../../containers/timeline/all'; @@ -40,6 +41,7 @@ import { OnDeleteOneTimeline, } from './types'; import { DEFAULT_SORT_FIELD, DEFAULT_SORT_DIRECTION } from './constants'; +import { useTimelineTypes } from './use_timeline_types'; interface OwnProps { apolloClient: ApolloClient; @@ -103,7 +105,21 @@ export const StatefulOpenTimelineComponent = React.memo( /** The requested field to sort on */ const [sortField, setSortField] = useState(DEFAULT_SORT_FIELD); - const { fetchAllTimeline, timelines, loading, totalCount, refetch } = useGetAllTimeline(); + const { timelineType, timelineTabs, timelineFilters } = useTimelineTypes(); + const { fetchAllTimeline, timelines, loading, totalCount } = useGetAllTimeline(); + + const refetch = useCallback(() => { + fetchAllTimeline({ + pageInfo: { + pageIndex: pageIndex + 1, + pageSize, + }, + search, + sort: { sortField: sortField as SortFieldTimeline, sortOrder: sortDirection as Direction }, + onlyUserFavorite: onlyFavorites, + timelineType, + }); + }, [pageIndex, pageSize, search, sortField, sortDirection, timelineType, onlyFavorites]); /** Invoked when the user presses enters to submit the text in the search input */ const onQueryChange: OnQueryChange = useCallback((query: EuiSearchBarQuery) => { @@ -139,6 +155,7 @@ export const StatefulOpenTimelineComponent = React.memo( if (timelineIds.includes(timeline.savedObjectId || '')) { createNewTimeline({ id: 'timeline-1', columns: defaultHeaders, show: false }); } + await apolloClient.mutate< DeleteTimelineMutation.Mutation, DeleteTimelineMutation.Variables @@ -229,27 +246,8 @@ export const StatefulOpenTimelineComponent = React.memo( }, []); useEffect(() => { - fetchAllTimeline({ - pageInfo: { - pageIndex: pageIndex + 1, - pageSize, - }, - search, - sort: { sortField: sortField as SortFieldTimeline, sortOrder: sortDirection as Direction }, - onlyUserFavorite: onlyFavorites, - timelines, - totalCount, - }); - }, [ - pageIndex, - pageSize, - search, - sortField, - sortDirection, - timelines, - totalCount, - onlyFavorites, - ]); + refetch(); + }, [refetch]); return !isModal ? ( ( selectedItems={selectedItems} sortDirection={sortDirection} sortField={sortField} + tabs={timelineTabs} title={title} totalSearchResultsCount={totalCount} /> @@ -303,6 +302,7 @@ export const StatefulOpenTimelineComponent = React.memo( selectedItems={selectedItems} sortDirection={sortDirection} sortField={sortField} + tabs={timelineFilters} title={title} totalSearchResultsCount={totalCount} /> diff --git a/x-pack/plugins/siem/public/components/open_timeline/open_timeline.test.tsx b/x-pack/plugins/siem/public/components/open_timeline/open_timeline.test.tsx index e010d54d711c3..449e1b169cea6 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/open_timeline.test.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/open_timeline.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { ThemeProvider } from 'styled-components'; import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../pages/timelines/timelines_page'; -import { OpenTimelineResult } from './types'; +import { OpenTimelineResult, OpenTimelineProps } from './types'; import { TimelinesTableProps } from './timelines_table'; import { mockTimelineResults } from '../../mock/timeline_results'; import { OpenTimeline } from './open_timeline'; @@ -25,75 +25,41 @@ describe('OpenTimeline', () => { let mockResults: OpenTimelineResult[]; - beforeEach(() => { - mockResults = cloneDeep(mockTimelineResults); + const getDefaultTestProps = (mockSearchResults: OpenTimelineResult[]): OpenTimelineProps => ({ + deleteTimelines: jest.fn(), + defaultPageSize: DEFAULT_SEARCH_RESULTS_PER_PAGE, + isLoading: false, + itemIdToExpandedNotesRowMap: {}, + onAddTimelinesToFavorites: jest.fn(), + onDeleteSelected: jest.fn(), + onlyFavorites: false, + onOpenTimeline: jest.fn(), + onQueryChange: jest.fn(), + onSelectionChange: jest.fn(), + onTableChange: jest.fn(), + onToggleOnlyFavorites: jest.fn(), + onToggleShowNotes: jest.fn(), + pageIndex: 0, + pageSize: DEFAULT_SEARCH_RESULTS_PER_PAGE, + query: '', + searchResults: mockSearchResults, + selectedItems: [], + sortDirection: DEFAULT_SORT_DIRECTION, + sortField: DEFAULT_SORT_FIELD, + tabs:
, + title, + totalSearchResultsCount: mockSearchResults.length, }); - test('it renders the title row', () => { - const wrapper = mountWithIntl( - - - - ); - - expect( - wrapper - .find('[data-test-subj="title-row"]') - .first() - .exists() - ).toBe(true); + beforeEach(() => { + mockResults = cloneDeep(mockTimelineResults); }); test('it renders the search row', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -106,32 +72,10 @@ describe('OpenTimeline', () => { }); test('it renders the timelines table', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -144,32 +88,10 @@ describe('OpenTimeline', () => { }); test('it shows the delete action columns when onDeleteSelected and deleteTimelines are specified', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -182,31 +104,14 @@ describe('OpenTimeline', () => { }); test('it does NOT show the delete action columns when is onDeleteSelected undefined and deleteTimelines is specified', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); @@ -219,31 +124,14 @@ describe('OpenTimeline', () => { }); test('it does NOT show the delete action columns when is onDeleteSelected provided and deleteTimelines is undefined', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); @@ -256,30 +144,14 @@ describe('OpenTimeline', () => { }); test('it does NOT show the delete action when both onDeleteSelected and deleteTimelines are undefined', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); @@ -292,32 +164,13 @@ describe('OpenTimeline', () => { }); test('it renders an empty string when the query is an empty string', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: '', + }; const wrapper = mountWithIntl( - + ); @@ -330,32 +183,13 @@ describe('OpenTimeline', () => { }); test('it renders the expected message when the query just has spaces', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: ' ', + }; const wrapper = mountWithIntl( - + ); @@ -368,32 +202,13 @@ describe('OpenTimeline', () => { }); test('it echos the query when the query has non-whitespace characters', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: 'Would you like to go to Denver?', + }; const wrapper = mountWithIntl( - + ); @@ -406,32 +221,13 @@ describe('OpenTimeline', () => { }); test('trims whitespace from the ends of the query', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: ' Is it starting to feel cramped in here? ', + }; const wrapper = mountWithIntl( - + ); @@ -444,32 +240,13 @@ describe('OpenTimeline', () => { }); test('it renders the expected message when the query is an empty string', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: '', + }; const wrapper = mountWithIntl( - + ); @@ -482,32 +259,13 @@ describe('OpenTimeline', () => { }); test('it renders the expected message when the query just has whitespace', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: ' ', + }; const wrapper = mountWithIntl( - + ); @@ -520,32 +278,13 @@ describe('OpenTimeline', () => { }); test('it includes the word "with" when the query has non-whitespace characters', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + query: 'How was your day?', + }; const wrapper = mountWithIntl( - + ); diff --git a/x-pack/plugins/siem/public/components/open_timeline/open_timeline.tsx b/x-pack/plugins/siem/public/components/open_timeline/open_timeline.tsx index 26aeab87e3510..e172a006abe4b 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/open_timeline.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/open_timeline.tsx @@ -11,7 +11,6 @@ import { OPEN_TIMELINE_CLASS_NAME } from './helpers'; import { OpenTimelineProps, OpenTimelineResult } from './types'; import { SearchRow } from './search_row'; import { TimelinesTable } from './timelines_table'; -import { TitleRow } from './title_row'; import { ImportDataModal } from '../import_data_modal'; import * as i18n from './translations'; import { importTimelines } from '../../containers/timeline/api'; @@ -52,7 +51,7 @@ export const OpenTimeline = React.memo( sortDirection, setImportDataModalToggle, sortField, - title, + tabs, totalSearchResultsCount, }) => { const tableRef = useRef>(); @@ -98,9 +97,9 @@ export const OpenTimeline = React.memo( const onRefreshBtnClick = useCallback(() => { if (refetch != null) { - refetch(); + refetch(searchResults, totalSearchResultsCount); } - }, [refetch]); + }, [refetch, searchResults, totalSearchResultsCount]); const handleCloseModal = useCallback(() => { if (setImportDataModalToggle != null) { @@ -112,9 +111,9 @@ export const OpenTimeline = React.memo( setImportDataModalToggle(false); } if (refetch != null) { - refetch(); + refetch(searchResults, totalSearchResultsCount); } - }, [setImportDataModalToggle, refetch]); + }, [setImportDataModalToggle, refetch, searchResults, totalSearchResultsCount]); return ( <> @@ -143,21 +142,15 @@ export const OpenTimeline = React.memo( /> - - - + {tabs} + diff --git a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx index 46a0d46c1e0d1..178c69e6957e1 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/index.test.tsx @@ -28,6 +28,15 @@ jest.mock('../../../containers/timeline/all', () => { getAllTimeline: originalModule.getAllTimeline, }; }); +jest.mock('../use_timeline_types', () => { + return { + useTimelineTypes: jest.fn().mockReturnValue({ + timelineType: 'default', + timelineTabs:
, + timelineFilters:
, + }), + }; +}); describe('OpenTimelineModal', () => { const theme = () => ({ eui: euiDarkVars, darkMode: true }); diff --git a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx index 2c3adb138b7ac..a610884d287a6 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.test.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { ThemeProvider } from 'styled-components'; import { DEFAULT_SEARCH_RESULTS_PER_PAGE } from '../../../pages/timelines/timelines_page'; -import { OpenTimelineResult } from '../types'; +import { OpenTimelineResult, OpenTimelineProps } from '../types'; import { TimelinesTableProps } from '../timelines_table'; import { mockTimelineResults } from '../../../mock/timeline_results'; import { OpenTimelineModalBody } from './open_timeline_modal_body'; @@ -22,40 +22,43 @@ jest.mock('../../../lib/kibana'); describe('OpenTimelineModal', () => { const theme = () => ({ eui: euiDarkVars, darkMode: true }); const title = 'All Timelines / Open Timelines'; - let mockResults: OpenTimelineResult[]; + const getDefaultTestProps = (mockSearchResults: OpenTimelineResult[]): OpenTimelineProps => ({ + deleteTimelines: jest.fn(), + defaultPageSize: DEFAULT_SEARCH_RESULTS_PER_PAGE, + isLoading: false, + itemIdToExpandedNotesRowMap: {}, + onAddTimelinesToFavorites: jest.fn(), + onDeleteSelected: jest.fn(), + onlyFavorites: false, + onOpenTimeline: jest.fn(), + onQueryChange: jest.fn(), + onSelectionChange: jest.fn(), + onTableChange: jest.fn(), + onToggleOnlyFavorites: jest.fn(), + onToggleShowNotes: jest.fn(), + pageIndex: 0, + pageSize: DEFAULT_SEARCH_RESULTS_PER_PAGE, + query: '', + searchResults: mockSearchResults, + selectedItems: [], + sortDirection: DEFAULT_SORT_DIRECTION, + sortField: DEFAULT_SORT_FIELD, + tabs:
, + title, + totalSearchResultsCount: mockSearchResults.length, + }); + beforeEach(() => { mockResults = cloneDeep(mockTimelineResults); }); test('it renders the title row', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -68,32 +71,10 @@ describe('OpenTimelineModal', () => { }); test('it renders the search row', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -106,32 +87,10 @@ describe('OpenTimelineModal', () => { }); test('it renders the timelines table', () => { + const defaultProps = getDefaultTestProps(mockResults); const wrapper = mountWithIntl( - + ); @@ -144,32 +103,14 @@ describe('OpenTimelineModal', () => { }); test('it shows the delete action when onDeleteSelected and deleteTimelines are specified', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: jest.fn(), + deleteTimelines: jest.fn(), + }; const wrapper = mountWithIntl( - + ); @@ -182,31 +123,14 @@ describe('OpenTimelineModal', () => { }); test('it does NOT show the delete when is onDeleteSelected undefined and deleteTimelines is specified', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); @@ -219,31 +143,14 @@ describe('OpenTimelineModal', () => { }); test('it does NOT show the delete action when is onDeleteSelected provided and deleteTimelines is undefined', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); @@ -256,30 +163,14 @@ describe('OpenTimelineModal', () => { }); test('it does NOT show extended columns when both onDeleteSelected and deleteTimelines are undefined', () => { + const defaultProps = { + ...getDefaultTestProps(mockResults), + onDeleteSelected: undefined, + deleteTimelines: undefined, + }; const wrapper = mountWithIntl( - + ); diff --git a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.tsx b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.tsx index 60ebf2118d556..ebfd01274ab41 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/open_timeline_modal/open_timeline_modal_body.tsx @@ -42,6 +42,7 @@ export const OpenTimelineModalBody = memo( selectedItems, sortDirection, sortField, + tabs, title, totalSearchResultsCount, }) => { @@ -52,6 +53,7 @@ export const OpenTimelineModalBody = memo( : ['duplicate']; return actions.filter(action => !hideActions.includes(action)); }, [onDeleteSelected, deleteTimelines, hideActions]); + return ( <> @@ -62,15 +64,17 @@ export const OpenTimelineModalBody = memo( selectedTimelinesCount={selectedItems.length} title={title} /> - - + <> + + diff --git a/x-pack/plugins/siem/public/components/open_timeline/search_row/index.tsx b/x-pack/plugins/siem/public/components/open_timeline/search_row/index.tsx index 55fce1f1c1ed0..b05be6b44418a 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/search_row/index.tsx +++ b/x-pack/plugins/siem/public/components/open_timeline/search_row/index.tsx @@ -35,7 +35,7 @@ SearchRowFlexGroup.displayName = 'SearchRowFlexGroup'; type Props = Pick< OpenTimelineProps, 'onlyFavorites' | 'onQueryChange' | 'onToggleOnlyFavorites' | 'query' | 'totalSearchResultsCount' ->; +> & { tabs?: JSX.Element }; const searchBox = { placeholder: i18n.SEARCH_PLACEHOLDER, @@ -46,7 +46,14 @@ const searchBox = { * Renders the row containing the search input and Only Favorites filter */ export const SearchRow = React.memo( - ({ onlyFavorites, onQueryChange, onToggleOnlyFavorites, query, totalSearchResultsCount }) => { + ({ + onlyFavorites, + onQueryChange, + onToggleOnlyFavorites, + query, + totalSearchResultsCount, + tabs, + }) => { return ( @@ -55,14 +62,17 @@ export const SearchRow = React.memo( - - - {i18n.ONLY_FAVORITES} - + + <> + + {i18n.ONLY_FAVORITES} + + {tabs} + diff --git a/x-pack/plugins/siem/public/components/open_timeline/translations.ts b/x-pack/plugins/siem/public/components/open_timeline/translations.ts index 7914e368166db..80c044c0a1d9f 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/translations.ts +++ b/x-pack/plugins/siem/public/components/open_timeline/translations.ts @@ -146,6 +146,20 @@ export const SUCCESSFULLY_EXPORTED_TIMELINES = (totalTimelines: number) => 'Successfully exported {totalTimelines, plural, =0 {all timelines} =1 {{totalTimelines} timeline} other {{totalTimelines} timelines}}', }); +export const FILTER_TIMELINES = (timelineType: string) => + i18n.translate('xpack.siem.open.timeline.filterByTimelineTypesTitle', { + values: { timelineType }, + defaultMessage: 'Only {timelineType}', + }); + +export const TAB_TIMELINES = i18n.translate('xpack.siem.timelines.components.tabs.timelinesTitle', { + defaultMessage: 'Timelines', +}); + +export const TAB_TEMPLATES = i18n.translate('xpack.siem.timelines.components.tabs.templatesTitle', { + defaultMessage: 'Templates', +}); + export const IMPORT_TIMELINE_BTN_TITLE = i18n.translate( 'xpack.siem.timelines.components.importTimelineModal.importTimelineTitle', { diff --git a/x-pack/plugins/siem/public/components/open_timeline/types.ts b/x-pack/plugins/siem/public/components/open_timeline/types.ts index 41999c6249277..4d953f6fa775e 100644 --- a/x-pack/plugins/siem/public/components/open_timeline/types.ts +++ b/x-pack/plugins/siem/public/components/open_timeline/types.ts @@ -8,8 +8,7 @@ import { SetStateAction, Dispatch } from 'react'; import { AllTimelinesVariables } from '../../containers/timeline/all'; import { TimelineModel } from '../../store/timeline/model'; import { NoteResult } from '../../graphql/types'; -import { Refetch } from '../../store/inputs/model'; -import { TimelineType } from '../../../common/types/timeline'; +import { TimelineType, TimelineTypeLiteral } from '../../../common/types/timeline'; /** The users who added a timeline to favorites */ export interface FavoriteTimelineResult { @@ -150,7 +149,7 @@ export interface OpenTimelineProps { /** The currently applied search criteria */ query: string; /** Refetch table */ - refetch?: Refetch; + refetch?: (existingTimeline?: OpenTimelineResult[], existingCount?: number) => void; /** The results of executing a search */ searchResults: OpenTimelineResult[]; /** the currently-selected timelines in the table */ @@ -161,6 +160,8 @@ export interface OpenTimelineProps { sortDirection: 'asc' | 'desc'; /** the requested field to sort on */ sortField: string; + /** timeline / template timeline */ + tabs: JSX.Element; /** The title of the Open Timeline component */ title: string; /** The total (server-side) count of the search results */ @@ -188,3 +189,15 @@ export type DispatchUpdateTimeline = ({ to, ruleNote, }: UpdateTimeline) => () => void; + +export enum TimelineTabsStyle { + tab = 'tab', + filter = 'filter', +} + +export interface TimelineTab { + id: TimelineTypeLiteral; + name: string; + disabled: boolean; + href: string; +} diff --git a/x-pack/plugins/siem/public/components/open_timeline/use_timeline_types.tsx b/x-pack/plugins/siem/public/components/open_timeline/use_timeline_types.tsx new file mode 100644 index 0000000000000..1e23bc5bdda3c --- /dev/null +++ b/x-pack/plugins/siem/public/components/open_timeline/use_timeline_types.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import React, { useState, useCallback, useMemo } from 'react'; +import { useParams } from 'react-router-dom'; +import { EuiTabs, EuiTab, EuiSpacer, EuiFilterButton } from '@elastic/eui'; + +import { TimelineTypeLiteralWithNull, TimelineType } from '../../../common/types/timeline'; + +import { getTimelineTabsUrl } from '../link_to'; +import { useGetUrlSearch } from '../navigation/use_get_url_search'; +import { navTabs } from '../../pages/home/home_navigations'; + +import * as i18n from './translations'; +import { TimelineTabsStyle, TimelineTab } from './types'; + +export const useTimelineTypes = (): { + timelineType: TimelineTypeLiteralWithNull; + timelineTabs: JSX.Element; + timelineFilters: JSX.Element; +} => { + const urlSearch = useGetUrlSearch(navTabs.timelines); + const { tabName } = useParams<{ pageName: string; tabName: string }>(); + const [timelineType, setTimelineTypes] = useState( + tabName === TimelineType.default || tabName === TimelineType.template ? tabName : null + ); + + const getFilterOrTabs: (timelineTabsStyle: TimelineTabsStyle) => TimelineTab[] = ( + timelineTabsStyle: TimelineTabsStyle + ) => [ + { + id: TimelineType.default, + name: + timelineTabsStyle === TimelineTabsStyle.filter + ? i18n.FILTER_TIMELINES(i18n.TAB_TIMELINES) + : i18n.TAB_TIMELINES, + href: getTimelineTabsUrl(TimelineType.default, urlSearch), + disabled: false, + }, + { + id: TimelineType.template, + name: + timelineTabsStyle === TimelineTabsStyle.filter + ? i18n.FILTER_TIMELINES(i18n.TAB_TEMPLATES) + : i18n.TAB_TEMPLATES, + href: getTimelineTabsUrl(TimelineType.template, urlSearch), + disabled: false, + }, + ]; + + const onFilterClicked = useCallback( + (timelineTabsStyle, tabId) => { + if (timelineTabsStyle === TimelineTabsStyle.filter && tabId === timelineType) { + setTimelineTypes(null); + } else { + setTimelineTypes(tabId); + } + }, + [timelineType, setTimelineTypes] + ); + + const timelineTabs = useMemo(() => { + return ( + <> + + {getFilterOrTabs(TimelineTabsStyle.tab).map((tab: TimelineTab) => ( + + {tab.name} + + ))} + + + + ); + }, [tabName]); + + const timelineFilters = useMemo(() => { + return ( + <> + {getFilterOrTabs(TimelineTabsStyle.tab).map((tab: TimelineTab) => ( + + {tab.name} + + ))} + + ); + }, [timelineType]); + + return { + timelineType, + timelineTabs, + timelineFilters, + }; +}; diff --git a/x-pack/plugins/siem/public/components/recent_timelines/index.tsx b/x-pack/plugins/siem/public/components/recent_timelines/index.tsx index b641038f35ba6..d3532d9fd1025 100644 --- a/x-pack/plugins/siem/public/components/recent_timelines/index.tsx +++ b/x-pack/plugins/siem/public/components/recent_timelines/index.tsx @@ -10,6 +10,8 @@ import React, { useCallback, useMemo, useEffect } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { Dispatch } from 'redux'; +import { TimelineType } from '../../../common/types/timeline'; + import { useGetAllTimeline } from '../../containers/timeline/all'; import { SortFieldTimeline, Direction } from '../../graphql/types'; import { queryTimelineById, dispatchUpdateTimeline } from '../open_timeline/helpers'; @@ -62,7 +64,7 @@ const StatefulRecentTimelinesComponent = React.memo( [filterBy] ); - const { fetchAllTimeline, timelines, totalCount, loading } = useGetAllTimeline(); + const { fetchAllTimeline, timelines, loading } = useGetAllTimeline(); useEffect(() => { fetchAllTimeline({ @@ -76,10 +78,9 @@ const StatefulRecentTimelinesComponent = React.memo( sortOrder: Direction.desc, }, onlyUserFavorite: filterBy === 'favorites', - timelines, - totalCount, + timelineType: TimelineType.default, }); - }, [filterBy, timelines, totalCount]); + }, [filterBy]); return ( <> diff --git a/x-pack/plugins/siem/public/components/timeline/selectable_timeline/index.tsx b/x-pack/plugins/siem/public/components/timeline/selectable_timeline/index.tsx index 4cc89e5bdba73..964bb2061333d 100644 --- a/x-pack/plugins/siem/public/components/timeline/selectable_timeline/index.tsx +++ b/x-pack/plugins/siem/public/components/timeline/selectable_timeline/index.tsx @@ -23,6 +23,8 @@ import styled from 'styled-components'; import { useGetAllTimeline } from '../../../containers/timeline/all'; import { SortFieldTimeline, Direction } from '../../../graphql/types'; +import { TimelineType, TimelineTypeLiteralWithNull } from '../../../../common/types/timeline'; + import { isUntitled } from '../../open_timeline/helpers'; import * as i18nTimeline from '../../open_timeline/translations'; import { OpenTimelineResult } from '../../open_timeline/types'; @@ -71,6 +73,7 @@ const TIMELINE_ITEM_HEIGHT = 50; export interface GetSelectableOptions { timelines: OpenTimelineResult[]; onlyFavorites: boolean; + timelineType?: TimelineTypeLiteralWithNull; searchTimelineValue: string; } @@ -79,6 +82,7 @@ interface SelectableTimelineProps { getSelectableOptions: ({ timelines, onlyFavorites, + timelineType, searchTimelineValue, }: GetSelectableOptions) => EuiSelectableOption[]; onClosePopover: () => void; @@ -228,10 +232,9 @@ const SelectableTimelineComponent: React.FC = ({ sortOrder: Direction.desc, }, onlyUserFavorite: onlyFavorites, - timelines, - totalCount: timelineCount, + timelineType: TimelineType.default, }); - }, [onlyFavorites, pageSize, searchTimelineValue, timelines, timelineCount]); + }, [onlyFavorites, pageSize, searchTimelineValue]); return ( @@ -263,7 +266,12 @@ const SelectableTimelineComponent: React.FC = ({ }, }} singleSelection={true} - options={getSelectableOptions({ timelines, onlyFavorites, searchTimelineValue })} + options={getSelectableOptions({ + timelines, + onlyFavorites, + searchTimelineValue, + timelineType: TimelineType.default, + })} > {(list, search) => ( <> diff --git a/x-pack/plugins/siem/public/containers/timeline/all/index.gql_query.ts b/x-pack/plugins/siem/public/containers/timeline/all/index.gql_query.ts index 7d30b6c22a110..76aef8de4ad84 100644 --- a/x-pack/plugins/siem/public/containers/timeline/all/index.gql_query.ts +++ b/x-pack/plugins/siem/public/containers/timeline/all/index.gql_query.ts @@ -12,12 +12,14 @@ export const allTimelinesQuery = gql` $search: String $sort: SortTimeline $onlyUserFavorite: Boolean + $timelineType: String ) { getAllTimeline( pageInfo: $pageInfo search: $search sort: $sort onlyUserFavorite: $onlyUserFavorite + timelineType: $timelineType ) { totalCount timeline { diff --git a/x-pack/plugins/siem/public/containers/timeline/all/index.tsx b/x-pack/plugins/siem/public/containers/timeline/all/index.tsx index 62c8d21a2e944..e1d1edc1a8cec 100644 --- a/x-pack/plugins/siem/public/containers/timeline/all/index.tsx +++ b/x-pack/plugins/siem/public/containers/timeline/all/index.tsx @@ -6,7 +6,7 @@ import { getOr, noop } from 'lodash/fp'; import memoizeOne from 'memoize-one'; -import { useCallback, useState, useRef, useEffect } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { OpenTimelineResult } from '../../../components/open_timeline/types'; @@ -17,18 +17,24 @@ import { SortTimeline, TimelineResult, } from '../../../graphql/types'; -import { inputsModel, inputsActions } from '../../../store/inputs'; +import { inputsActions } from '../../../store/inputs'; import { useApolloClient } from '../../../utils/apollo_context'; import { allTimelinesQuery } from './index.gql_query'; import * as i18n from '../../../pages/timelines/translations'; +import { TimelineTypeLiteralWithNull } from '../../../../common/types/timeline'; export interface AllTimelinesArgs { - fetchAllTimeline: ({ onlyUserFavorite, pageInfo, search, sort }: AllTimelinesVariables) => void; + fetchAllTimeline: ({ + onlyUserFavorite, + pageInfo, + search, + sort, + timelineType, + }: AllTimelinesVariables) => void; timelines: OpenTimelineResult[]; loading: boolean; totalCount: number; - refetch: () => void; } export interface AllTimelinesVariables { @@ -36,8 +42,7 @@ export interface AllTimelinesVariables { pageInfo: PageInfoTimeline; search: string; sort: SortTimeline; - timelines: OpenTimelineResult[]; - totalCount: number; + timelineType: TimelineTypeLiteralWithNull; } export const ALL_TIMELINE_QUERY_ID = 'FETCH_ALL_TIMELINES'; @@ -80,25 +85,16 @@ export const getAllTimeline = memoizeOne( export const useGetAllTimeline = (): AllTimelinesArgs => { const dispatch = useDispatch(); const apolloClient = useApolloClient(); - const refetch = useRef(); const [, dispatchToaster] = useStateToaster(); const [allTimelines, setAllTimelines] = useState({ fetchAllTimeline: noop, loading: false, - refetch: refetch.current ?? noop, totalCount: 0, timelines: [], }); const fetchAllTimeline = useCallback( - async ({ - onlyUserFavorite, - pageInfo, - search, - sort, - timelines, - totalCount, - }: AllTimelinesVariables) => { + async ({ onlyUserFavorite, pageInfo, search, sort, timelineType }: AllTimelinesVariables) => { let didCancel = false; const abortCtrl = new AbortController(); @@ -107,15 +103,15 @@ export const useGetAllTimeline = (): AllTimelinesArgs => { if (apolloClient != null) { setAllTimelines({ ...allTimelines, - timelines: timelines ?? allTimelines.timelines, - totalCount: totalCount ?? allTimelines.totalCount, loading: true, }); + const variables: GetAllTimeline.Variables = { onlyUserFavorite, pageInfo, search, sort, + timelineType, }; const response = await apolloClient.query< GetAllTimeline.Query, @@ -130,25 +126,23 @@ export const useGetAllTimeline = (): AllTimelinesArgs => { }, }, }); + const totalCount = response?.data?.getAllTimeline?.totalCount ?? 0; + const timelines = response?.data?.getAllTimeline?.timeline ?? []; if (!didCancel) { dispatch( inputsActions.setQuery({ inputId: 'global', id: ALL_TIMELINE_QUERY_ID, loading: false, - refetch: refetch.current ?? noop, + refetch: fetchData, inspect: null, }) ); setAllTimelines({ fetchAllTimeline, loading: false, - refetch: refetch.current ?? noop, - totalCount: getOr(0, 'getAllTimeline.totalCount', response.data), - timelines: getAllTimeline( - JSON.stringify(variables), - getOr([], 'getAllTimeline.timeline', response.data) - ), + totalCount, + timelines: getAllTimeline(JSON.stringify(variables), timelines as TimelineResult[]), }); } } @@ -162,14 +156,12 @@ export const useGetAllTimeline = (): AllTimelinesArgs => { setAllTimelines({ fetchAllTimeline, loading: false, - refetch: noop, totalCount: 0, timelines: [], }); } } }; - refetch.current = fetchData; fetchData(); return () => { didCancel = true; @@ -188,6 +180,5 @@ export const useGetAllTimeline = (): AllTimelinesArgs => { return { ...allTimelines, fetchAllTimeline, - refetch: refetch.current ?? noop, }; }; diff --git a/x-pack/plugins/siem/public/graphql/introspection.json b/x-pack/plugins/siem/public/graphql/introspection.json index 4026a043c7778..c2b21957a9056 100644 --- a/x-pack/plugins/siem/public/graphql/introspection.json +++ b/x-pack/plugins/siem/public/graphql/introspection.json @@ -249,6 +249,12 @@ "description": "", "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, "defaultValue": null + }, + { + "name": "timelineType", + "description": "", + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "defaultValue": null } ], "type": { diff --git a/x-pack/plugins/siem/public/graphql/types.ts b/x-pack/plugins/siem/public/graphql/types.ts index 86890988c06b6..dd4e967b185b9 100644 --- a/x-pack/plugins/siem/public/graphql/types.ts +++ b/x-pack/plugins/siem/public/graphql/types.ts @@ -2235,6 +2235,8 @@ export interface GetAllTimelineQueryArgs { sort?: Maybe; onlyUserFavorite?: Maybe; + + timelineType?: Maybe; } export interface AuthenticationsSourceArgs { timerange: TimerangeInput; @@ -4012,6 +4014,7 @@ export namespace GetAllTimeline { search?: Maybe; sort?: Maybe; onlyUserFavorite?: Maybe; + timelineType?: Maybe; }; export type Query = { diff --git a/x-pack/plugins/siem/public/pages/timelines/index.tsx b/x-pack/plugins/siem/public/pages/timelines/index.tsx index aa5c891de3628..343be5cbe3839 100644 --- a/x-pack/plugins/siem/public/pages/timelines/index.tsx +++ b/x-pack/plugins/siem/public/pages/timelines/index.tsx @@ -6,11 +6,66 @@ import React from 'react'; import { ApolloConsumer } from 'react-apollo'; +import { Switch, Route, Redirect } from 'react-router-dom'; + +import { ChromeBreadcrumb } from '../../../../../../src/core/public'; + +import { TimelineType } from '../../../common/types/timeline'; +import { TAB_TIMELINES, TAB_TEMPLATES } from '../../components/open_timeline/translations'; +import { getTimelinesUrl } from '../../components/link_to'; +import { TimelineRouteSpyState } from '../../utils/route/types'; + +import { SiemPageName } from '../home/types'; import { TimelinesPage } from './timelines_page'; +import { PAGE_TITLE } from './translations'; +import { appendSearch } from '../../components/link_to/helpers'; +const timelinesPagePath = `/:pageName(${SiemPageName.timelines})/:tabName(${TimelineType.default}|${TimelineType.template})`; +const timelinesDefaultPath = `/${SiemPageName.timelines}/${TimelineType.default}`; + +const TabNameMappedToI18nKey: Record = { + [TimelineType.default]: TAB_TIMELINES, + [TimelineType.template]: TAB_TEMPLATES, +}; + +export const getBreadcrumbs = ( + params: TimelineRouteSpyState, + search: string[] +): ChromeBreadcrumb[] => { + let breadcrumb = [ + { + text: PAGE_TITLE, + href: `${getTimelinesUrl(appendSearch(search[1]))}`, + }, + ]; + + const tabName = params?.tabName; + if (!tabName) return breadcrumb; + + breadcrumb = [ + ...breadcrumb, + { + text: TabNameMappedToI18nKey[tabName], + href: '', + }, + ]; + return breadcrumb; +}; -export const Timelines = React.memo(() => ( - {client => } -)); +export const Timelines = React.memo(() => { + return ( + + + {client => } + + ( + + )} + /> + + ); +}); Timelines.displayName = 'Timelines'; diff --git a/x-pack/plugins/siem/public/store/timeline/model.ts b/x-pack/plugins/siem/public/store/timeline/model.ts index 7885064380eff..54e19812634ac 100644 --- a/x-pack/plugins/siem/public/store/timeline/model.ts +++ b/x-pack/plugins/siem/public/store/timeline/model.ts @@ -80,7 +80,7 @@ export interface TimelineModel { }; /** Title */ title: string; - /** timelineTypes: default | template */ + /** timelineType: default | template */ timelineType: TimelineTypeLiteralWithNull; /** an unique id for template timeline */ templateTimelineId: string | null; diff --git a/x-pack/plugins/siem/public/utils/route/types.ts b/x-pack/plugins/siem/public/utils/route/types.ts index d3eca36bd0d96..17b312a427c43 100644 --- a/x-pack/plugins/siem/public/utils/route/types.ts +++ b/x-pack/plugins/siem/public/utils/route/types.ts @@ -8,11 +8,13 @@ import * as H from 'history'; import React from 'react'; import { RouteComponentProps } from 'react-router-dom'; +import { TimelineType } from '../../../common/types/timeline'; + import { HostsTableType } from '../../store/hosts/model'; import { NetworkRouteType } from '../../pages/network/navigation/types'; import { FlowTarget } from '../../graphql/types'; -export type SiemRouteType = HostsTableType | NetworkRouteType; +export type SiemRouteType = HostsTableType | NetworkRouteType | TimelineType; export interface RouteSpyState { pageName: string; detailName: string | undefined; @@ -32,6 +34,10 @@ export interface NetworkRouteSpyState extends RouteSpyState { tabName: NetworkRouteType | undefined; } +export interface TimelineRouteSpyState extends RouteSpyState { + tabName: TimelineType | undefined; +} + export type RouteSpyAction = | { type: 'updateSearch'; diff --git a/x-pack/plugins/siem/server/graphql/timeline/resolvers.ts b/x-pack/plugins/siem/server/graphql/timeline/resolvers.ts index a33751179e93a..a40ef5466c780 100644 --- a/x-pack/plugins/siem/server/graphql/timeline/resolvers.ts +++ b/x-pack/plugins/siem/server/graphql/timeline/resolvers.ts @@ -52,7 +52,8 @@ export const createTimelineResolvers = ( args.onlyUserFavorite || null, args.pageInfo || null, args.search || null, - args.sort || null + args.sort || null, + args.timelineType || null ); }, }, diff --git a/x-pack/plugins/siem/server/graphql/timeline/schema.gql.ts b/x-pack/plugins/siem/server/graphql/timeline/schema.gql.ts index bc2b3a53d85f3..a1c13fd21a88e 100644 --- a/x-pack/plugins/siem/server/graphql/timeline/schema.gql.ts +++ b/x-pack/plugins/siem/server/graphql/timeline/schema.gql.ts @@ -278,7 +278,7 @@ export const timelineSchema = gql` extend type Query { getOneTimeline(id: ID!): TimelineResult! - getAllTimeline(pageInfo: PageInfoTimeline, search: String, sort: SortTimeline, onlyUserFavorite: Boolean): ResponseTimelines! + getAllTimeline(pageInfo: PageInfoTimeline, search: String, sort: SortTimeline, onlyUserFavorite: Boolean, timelineType: String): ResponseTimelines! } extend type Mutation { diff --git a/x-pack/plugins/siem/server/graphql/types.ts b/x-pack/plugins/siem/server/graphql/types.ts index 6a35ba08f8e43..d74086357edbe 100644 --- a/x-pack/plugins/siem/server/graphql/types.ts +++ b/x-pack/plugins/siem/server/graphql/types.ts @@ -2237,6 +2237,8 @@ export interface GetAllTimelineQueryArgs { sort?: Maybe; onlyUserFavorite?: Maybe; + + timelineType?: Maybe; } export interface AuthenticationsSourceArgs { timerange: TimerangeInput; @@ -2693,6 +2695,8 @@ export namespace QueryResolvers { sort?: Maybe; onlyUserFavorite?: Maybe; + + timelineType?: Maybe; } } diff --git a/x-pack/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts b/x-pack/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts index 99621f1391acb..4a79dada07171 100644 --- a/x-pack/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts +++ b/x-pack/plugins/siem/server/lib/timeline/routes/import_timelines_route.ts @@ -119,35 +119,35 @@ export const importTimelinesRoute = ( return null; } const { - savedObjectId, + savedObjectId = null, pinnedEventIds, globalNotes, eventNotes, templateTimelineId, templateTimelineVersion, timelineType, + version = null, } = parsedTimeline; const parsedTimelineObject = omit( timelineSavedObjectOmittedFields, parsedTimeline ); + let newTimeline = null; try { const templateTimeline = templateTimelineId != null ? await getTemplateTimeline(frameworkRequest, templateTimelineId) : null; + const timeline = - templateTimeline?.savedObjectId != null || savedObjectId != null - ? await getTimeline( - frameworkRequest, - templateTimeline?.savedObjectId ?? savedObjectId - ) - : null; + savedObjectId != null && + (await getTimeline(frameworkRequest, savedObjectId)); const isHandlingTemplateTimeline = timelineType === TimelineType.template; + if ( (timeline == null && !isHandlingTemplateTimeline) || - (templateTimeline == null && isHandlingTemplateTimeline) + (timeline == null && templateTimeline == null && isHandlingTemplateTimeline) ) { // create timeline / template timeline newTimeline = await createTimelines( @@ -156,7 +156,9 @@ export const importTimelinesRoute = ( null, // timelineSavedObjectId null, // timelineVersion pinnedEventIds, - [...globalNotes, ...eventNotes], + isHandlingTemplateTimeline + ? globalNotes + : [...globalNotes, ...eventNotes], [] // existing note ids ); @@ -165,6 +167,7 @@ export const importTimelinesRoute = ( status_code: 200, }); } else if ( + timeline && timeline != null && templateTimeline != null && isHandlingTemplateTimeline @@ -172,8 +175,8 @@ export const importTimelinesRoute = ( // update template timeline const errorObj = checkIsFailureCases( isHandlingTemplateTimeline, - timeline.version, - templateTimeline.templateTimelineVersion ?? null, + version, + templateTimelineVersion ?? null, timeline, templateTimeline ); @@ -198,16 +201,16 @@ export const importTimelinesRoute = ( } else { resolve( createBulkErrorObject({ - id: savedObjectId, + id: savedObjectId ?? 'unknown', statusCode: 409, - message: `timeline_id: "${timeline?.savedObjectId}" already exists`, + message: `timeline_id: "${savedObjectId}" already exists`, }) ); } } catch (err) { resolve( createBulkErrorObject({ - id: savedObjectId, + id: savedObjectId ?? 'unknown', statusCode: 400, message: err.message, }) diff --git a/x-pack/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts b/x-pack/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts index a49627d40c8f5..3f46b9ba91dc4 100644 --- a/x-pack/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts +++ b/x-pack/plugins/siem/server/lib/timeline/routes/utils/import_timelines.ts @@ -18,7 +18,8 @@ export interface ImportTimelinesSchema { } export type ImportedTimeline = SavedTimeline & { - savedObjectId: string; + savedObjectId: string | null; + version: string | null; pinnedEventIds: string[]; globalNotes: NoteResult[]; eventNotes: NoteResult[]; @@ -86,16 +87,18 @@ export const isBulkError = ( return has('error', importRuleResponse); }; +/** + * This fields do not exists in savedObject mapping, but exist in Users' import, + * exclude them here to avoid creating savedObject failure + */ export const timelineSavedObjectOmittedFields = [ 'globalNotes', 'eventNotes', 'pinnedEventIds', - 'version', 'savedObjectId', 'created', 'createdBy', 'updated', 'updatedBy', - 'templateTimelineId', - 'templateTimelineVersion', + 'version', ]; diff --git a/x-pack/plugins/siem/server/lib/timeline/saved_object.ts b/x-pack/plugins/siem/server/lib/timeline/saved_object.ts index d2df7589f3c4a..6d022ab42fa7b 100644 --- a/x-pack/plugins/siem/server/lib/timeline/saved_object.ts +++ b/x-pack/plugins/siem/server/lib/timeline/saved_object.ts @@ -47,7 +47,8 @@ export interface Timeline { onlyUserFavorite: boolean | null, pageInfo: PageInfoTimeline | null, search: string | null, - sort: SortTimeline | null + sort: SortTimeline | null, + timelineType: string | null ) => Promise; persistFavorite: ( @@ -94,12 +95,24 @@ export const getTimelineByTemplateTimelineId = async ( return getAllSavedTimeline(request, options); }; +/** The filter here is able to handle the legacy data, + * which has no timelineType exists in the savedObject */ +const getTimelineTypeFilter = (timelineType: string | null) => { + return timelineType === TimelineType.template + ? `siem-ui-timeline.attributes.timelineType: ${TimelineType.template}` /** Show only whose timelineType exists and equals to "template" */ + : /** Show me every timeline whose timelineType is not "template". + * which includes timelineType === 'default' and + * those timelineType doesn't exists */ + `not siem-ui-timeline.attributes.timelineType: ${TimelineType.template}`; +}; + export const getAllTimeline = async ( request: FrameworkRequest, onlyUserFavorite: boolean | null, pageInfo: PageInfoTimeline | null, search: string | null, - sort: SortTimeline | null + sort: SortTimeline | null, + timelineType: string | null ): Promise => { const options: SavedObjectsFindOptions = { type: timelineSavedObjectType, @@ -109,6 +122,7 @@ export const getAllTimeline = async ( searchFields: onlyUserFavorite ? ['title', 'description', 'favorite.keySearch'] : ['title', 'description'], + filter: getTimelineTypeFilter(timelineType), sortField: sort != null ? sort.sortField : undefined, sortOrder: sort != null ? sort.sortOrder : undefined, }; From b8bea5b8b2798dac2fe1546c53eded434d408a50 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Tue, 5 May 2020 20:52:56 -0400 Subject: [PATCH 54/72] [Canvas] move files from legacy/plugins to plugins (#65283) * Moves the files * Rename legacy/plugins/canvas paths * Correct paths * Fix shareable_runtime and storybook * ESLint Fixes * Fix jest test and paths --- .eslintignore | 8 +-- .eslintrc.js | 22 +++--- .github/CODEOWNERS | 2 +- .sass-lint.yml | 4 +- package.json | 2 +- src/cli/cluster/cluster_manager.ts | 2 +- src/dev/precommit_hook/casing_check_config.js | 6 +- src/dev/storybook/aliases.ts | 2 +- test/scripts/jenkins_xpack.sh | 2 +- x-pack/.i18nrc.json | 2 +- x-pack/.kibana-plugin-helpers.json | 4 +- x-pack/legacy/plugins/canvas/i18n/index.ts | 19 ----- x-pack/legacy/plugins/canvas/index.js | 68 ------------------ x-pack/legacy/plugins/canvas/public/index.ts | 31 -------- x-pack/legacy/plugins/canvas/public/legacy.ts | 53 -------------- .../canvas/public/legacy_plugin_support.ts | 47 ------------ .../public/legacy_register_interpreter.ts | 18 ----- .../plugins/canvas/public/legacy_start.ts | 27 ------- .../canvas/public/lib/function_definitions.js | 17 ----- x-pack/legacy/plugins/canvas/types/index.ts | 16 ----- x-pack/package.json | 2 +- x-pack/{legacy => }/plugins/canvas/.gitignore | 0 .../{legacy => }/plugins/canvas/.prettierrc | 0 .../plugins/canvas/.storybook/.babelrc | 0 .../plugins/canvas/.storybook/addons.js | 0 .../plugins/canvas/.storybook/config.js | 6 +- .../plugins/canvas/.storybook/constants.js | 2 +- .../plugins/canvas/.storybook/dll_contexts.js | 10 +-- .../plugins/canvas/.storybook/middleware.js | 0 .../canvas/.storybook/preview-head.html | 0 .../canvas/.storybook/storyshots.test.js | 9 ++- .../canvas/.storybook/webpack.config.js | 0 .../canvas/.storybook/webpack.dll.config.js | 0 x-pack/{legacy => }/plugins/canvas/README.md | 0 .../__tests__/fixtures/elasticsearch.js | 0 .../fixtures/elasticsearch_plugin.js | 0 .../__tests__/fixtures/function_specs.ts | 2 +- .../canvas/__tests__/fixtures/kibana.js | 2 +- .../canvas/__tests__/fixtures/workpads.ts | 0 .../__tests__/helpers/function_wrapper.js | 0 .../elements/area_chart/index.ts | 0 .../elements/bubble_chart/index.ts | 0 .../canvas_plugin_src/elements/debug/index.ts | 0 .../elements/dropdown_filter/index.ts | 0 .../elements/filter_debug/index.ts | 0 .../elements/horizontal_bar_chart/index.ts | 0 .../elements/horizontal_progress_bar/index.ts | 0 .../horizontal_progress_pill/index.ts | 0 .../canvas_plugin_src/elements/image/index.ts | 0 .../canvas_plugin_src/elements/index.ts | 0 .../elements/line_chart/index.ts | 0 .../elements/markdown/index.ts | 0 .../elements/metric/index.ts | 0 .../canvas_plugin_src/elements/pie/index.ts | 0 .../canvas_plugin_src/elements/plot/index.ts | 0 .../elements/progress_gauge/index.ts | 0 .../elements/progress_semicircle/index.ts | 0 .../elements/progress_wheel/index.ts | 0 .../elements/repeat_image/index.ts | 0 .../elements/reveal_image/index.ts | 0 .../canvas_plugin_src/elements/shape/index.ts | 0 .../canvas_plugin_src/elements/table/index.ts | 0 .../elements/time_filter/index.ts | 0 .../elements/vert_bar_chart/index.ts | 0 .../elements/vertical_progress_bar/index.ts | 0 .../elements/vertical_progress_pill/index.ts | 0 .../expression_types/embeddable.ts | 4 +- .../expression_types/embeddable_types.ts | 9 ++- .../expression_types/index.ts | 0 .../functions/browser/index.ts | 0 .../functions/browser/location.ts | 0 .../functions/browser/markdown.test.js | 0 .../functions/browser/markdown.ts | 0 .../functions/browser/urlparam.ts | 0 .../functions/common/__tests__/compare.js | 0 .../common/__tests__/fixtures/test_filters.js | 0 .../__tests__/fixtures/test_pointseries.js | 0 .../common/__tests__/fixtures/test_styles.js | 0 .../common/__tests__/fixtures/test_tables.ts | 18 ++--- .../functions/common/__tests__/image.js | 0 .../functions/common/__tests__/progress.js | 0 .../functions/common/all.test.js | 0 .../canvas_plugin_src/functions/common/all.ts | 0 .../functions/common/alterColumn.test.js | 0 .../functions/common/alterColumn.ts | 0 .../functions/common/any.test.js | 0 .../canvas_plugin_src/functions/common/any.ts | 0 .../functions/common/as.test.js | 0 .../canvas_plugin_src/functions/common/as.ts | 0 .../functions/common/axisConfig.ts | 0 .../functions/common/axis_config.test.js | 0 .../functions/common/case.test.js | 0 .../functions/common/case.ts | 0 .../functions/common/clear.test.js | 0 .../functions/common/clear.ts | 0 .../functions/common/columns.test.js | 0 .../functions/common/columns.ts | 0 .../functions/common/compare.ts | 0 .../functions/common/containerStyle.ts | 0 .../functions/common/container_style.test.js | 0 .../functions/common/context.test.js | 0 .../functions/common/context.ts | 0 .../functions/common/csv.test.js | 0 .../canvas_plugin_src/functions/common/csv.ts | 0 .../functions/common/date.test.js | 0 .../functions/common/date.ts | 0 .../functions/common/do.test.js | 0 .../canvas_plugin_src/functions/common/do.ts | 0 .../functions/common/dropdownControl.ts | 0 .../functions/common/dropdown_control.test.js | 0 .../functions/common/eq.test.js | 0 .../canvas_plugin_src/functions/common/eq.ts | 0 .../functions/common/exactly.test.js | 0 .../functions/common/exactly.ts | 0 .../functions/common/filterrows.test.js | 0 .../functions/common/filterrows.ts | 0 .../functions/common/formatdate.test.js | 0 .../functions/common/formatdate.ts | 0 .../functions/common/formatnumber.test.js | 0 .../functions/common/formatnumber.ts | 0 .../functions/common/getCell.test.js | 0 .../functions/common/getCell.ts | 0 .../common/get_flot_axis_config.test.js | 0 .../functions/common/get_font_spec.test.js | 0 .../functions/common/get_tick_hash.test.js | 0 .../functions/common/gt.test.js | 0 .../canvas_plugin_src/functions/common/gt.ts | 0 .../functions/common/gte.test.js | 0 .../canvas_plugin_src/functions/common/gte.ts | 0 .../functions/common/head.test.js | 0 .../functions/common/head.ts | 0 .../functions/common/if.test.js | 0 .../canvas_plugin_src/functions/common/if.ts | 0 .../functions/common/image.ts | 0 .../functions/common/index.ts | 0 .../functions/common/join_rows.test.js | 0 .../functions/common/join_rows.ts | 0 .../functions/common/lt.test.js | 0 .../canvas_plugin_src/functions/common/lt.ts | 0 .../functions/common/lte.test.js | 0 .../canvas_plugin_src/functions/common/lte.ts | 0 .../functions/common/mapColumn.test.js | 0 .../functions/common/mapColumn.ts | 0 .../functions/common/map_center.ts | 0 .../functions/common/math.test.js | 0 .../functions/common/math.ts | 0 .../functions/common/metric.test.js | 0 .../functions/common/metric.ts | 0 .../functions/common/neq.test.js | 0 .../canvas_plugin_src/functions/common/neq.ts | 0 .../functions/common/palette.test.js | 0 .../functions/common/palette.ts | 0 .../functions/common/pie.test.js | 0 .../canvas_plugin_src/functions/common/pie.ts | 0 .../functions/common/plot.test.js | 0 .../common/plot/get_flot_axis_config.ts | 2 +- .../functions/common/plot/get_font_spec.ts | 0 .../functions/common/plot/get_tick_hash.ts | 0 .../functions/common/plot/index.ts | 0 .../common/plot/series_style_to_flot.ts | 0 .../functions/common/ply.test.js | 0 .../canvas_plugin_src/functions/common/ply.ts | 0 .../functions/common/progress.ts | 0 .../functions/common/render.test.js | 0 .../functions/common/render.ts | 0 .../functions/common/repeatImage.ts | 0 .../functions/common/repeat_image.test.js | 0 .../functions/common/replace.test.js | 0 .../functions/common/replace.ts | 0 .../functions/common/revealImage.ts | 0 .../functions/common/reveal_image.test.js | 0 .../functions/common/rounddate.test.js | 0 .../functions/common/rounddate.ts | 0 .../functions/common/rowCount.test.js | 0 .../functions/common/rowCount.ts | 0 .../functions/common/saved_lens.test.ts | 0 .../functions/common/saved_lens.ts | 0 .../functions/common/saved_map.test.ts | 0 .../functions/common/saved_map.ts | 2 +- .../functions/common/saved_search.test.ts | 0 .../functions/common/saved_search.ts | 0 .../common/saved_visualization.test.ts | 0 .../functions/common/saved_visualization.ts | 0 .../functions/common/seriesStyle.ts | 0 .../functions/common/series_style.test.js | 0 .../common/series_style_to_flot.test.js | 0 .../functions/common/shape.ts | 0 .../functions/common/sort.test.js | 0 .../functions/common/sort.ts | 0 .../functions/common/staticColumn.test.js | 0 .../functions/common/staticColumn.ts | 0 .../functions/common/string.test.js | 0 .../functions/common/string.ts | 0 .../functions/common/switch.test.js | 0 .../functions/common/switch.ts | 0 .../functions/common/table.test.js | 0 .../functions/common/table.ts | 0 .../functions/common/tail.test.js | 0 .../functions/common/tail.ts | 0 .../functions/common/time_range.ts | 0 .../functions/common/timefilter.test.js | 0 .../functions/common/timefilter.ts | 0 .../functions/common/timefilterControl.ts | 0 .../common/timefilter_control.test.js | 0 .../functions/server/demodata.test.ts | 0 .../functions/server/demodata/ci.json | 0 .../server/demodata/demo_rows_types.ts | 0 .../server/demodata/get_demo_rows.ts | 0 .../functions/server/demodata/index.ts | 0 .../functions/server/demodata/shirts.json | 0 .../functions/server/escount.ts | 2 +- .../functions/server/esdocs.ts | 2 +- .../functions/server/essql.ts | 2 +- .../server/get_expression_type.test.js | 0 .../functions/server/get_field_names.test.ts | 0 .../functions/server/index.ts | 0 .../server/is_column_reference.test.ts | 0 .../functions/server/pointseries.test.js | 0 .../functions/server/pointseries/index.ts | 0 .../pointseries/lib/get_expression_type.js | 0 .../server/pointseries/lib/get_field_names.ts | 0 .../pointseries/lib/is_column_reference.ts | 0 .../canvas_plugin_src/lib/elastic_logo.js | 0 .../canvas_plugin_src/lib/elastic_outline.js | 0 .../canvas_plugin_src/lib/flot-charts/API.md | 0 .../lib/flot-charts/index.js | 0 .../lib/flot-charts/jquery.colorhelpers.js | 0 .../lib/flot-charts/jquery.flot.canvas.js | 0 .../lib/flot-charts/jquery.flot.categories.js | 0 .../lib/flot-charts/jquery.flot.crosshair.js | 0 .../lib/flot-charts/jquery.flot.errorbars.js | 0 .../flot-charts/jquery.flot.fillbetween.js | 0 .../lib/flot-charts/jquery.flot.image.js | 0 .../lib/flot-charts/jquery.flot.js | 0 .../lib/flot-charts/jquery.flot.navigate.js | 0 .../lib/flot-charts/jquery.flot.resize.js | 0 .../lib/flot-charts/jquery.flot.selection.js | 0 .../lib/flot-charts/jquery.flot.stack.js | 0 .../lib/flot-charts/jquery.flot.symbol.js | 0 .../lib/flot-charts/jquery.flot.threshold.js | 0 .../lib/flot-charts/jquery.flot.time.js | 0 .../canvas/canvas_plugin_src/plugin.ts | 6 +- .../advanced_filter.examples.storyshot | 0 .../__examples__/advanced_filter.examples.tsx | 0 .../component/advanced_filter.scss | 0 .../component/advanced_filter.tsx | 0 .../advanced_filter/component/index.ts | 0 .../renderers/advanced_filter/index.tsx | 0 .../canvas_plugin_src/renderers/debug.js | 0 .../dropdown_filter.examples.storyshot | 0 .../__examples__/dropdown_filter.examples.tsx | 0 .../component/dropdown_filter.scss | 0 .../component/dropdown_filter.tsx | 0 .../dropdown_filter/component/index.ts | 0 .../renderers/dropdown_filter/index.tsx | 0 .../renderers/embeddable/embeddable.scss | 0 .../renderers/embeddable/embeddable.tsx | 6 +- .../embeddable_input_to_expression.test.ts | 0 .../embeddable_input_to_expression.ts | 0 .../input_type_to_expression/lens.test.ts | 0 .../input_type_to_expression/lens.ts | 0 .../input_type_to_expression/map.test.ts | 2 +- .../input_type_to_expression/map.ts | 2 +- .../visualization.test.ts | 0 .../input_type_to_expression/visualization.ts | 0 .../renderers/error/error.scss | 0 .../renderers/error/index.js | 0 .../canvas_plugin_src/renderers/image.js | 0 .../canvas_plugin_src/renderers/index.js | 0 .../renderers/markdown/index.js | 2 +- .../__snapshots__/metric.stories.storyshot | 0 .../component/__examples__/metric.stories.tsx | 0 .../renderers/metric/component/index.ts | 0 .../renderers/metric/component/metric.tsx | 0 .../renderers/metric/index.tsx | 0 .../canvas_plugin_src/renderers/pie/index.js | 0 .../renderers/pie/plugins/pie.js | 0 .../canvas_plugin_src/renderers/plot/index.js | 0 .../renderers/plot/plot.scss | 0 .../renderers/plot/plugins/size.js | 0 .../renderers/plot/plugins/text.js | 0 .../renderers/progress/index.js | 0 .../renderers/progress/shapes/gauge.svg | 0 .../progress/shapes/horizontal_bar.svg | 0 .../progress/shapes/horizontal_pill.svg | 0 .../renderers/progress/shapes/index.js | 0 .../renderers/progress/shapes/semicircle.svg | 0 .../renderers/progress/shapes/unicorn.svg | 0 .../progress/shapes/vertical_bar.svg | 0 .../progress/shapes/vertical_pill.svg | 0 .../renderers/progress/shapes/wheel.svg | 0 .../renderers/repeat_image.js | 0 .../renderers/reveal_image/index.js | 0 .../renderers/reveal_image/reveal_image.scss | 0 .../renderers/shape/index.js | 0 .../renderers/shape/shapes/arrow.svg | 0 .../renderers/shape/shapes/arrow_multi.svg | 0 .../renderers/shape/shapes/bookmark.svg | 0 .../renderers/shape/shapes/circle.svg | 0 .../renderers/shape/shapes/cross.svg | 0 .../renderers/shape/shapes/hexagon.svg | 0 .../renderers/shape/shapes/index.ts | 0 .../renderers/shape/shapes/kite.svg | 0 .../renderers/shape/shapes/pentagon.svg | 0 .../renderers/shape/shapes/rhombus.svg | 0 .../renderers/shape/shapes/semicircle.svg | 0 .../renderers/shape/shapes/speech_bubble.svg | 0 .../renderers/shape/shapes/square.svg | 0 .../renderers/shape/shapes/star.svg | 0 .../renderers/shape/shapes/tag.svg | 0 .../renderers/shape/shapes/triangle.svg | 0 .../renderers/shape/shapes/triangle_right.svg | 0 .../canvas_plugin_src/renderers/table.js | 0 .../canvas_plugin_src/renderers/text.js | 0 .../time_filter.examples.storyshot | 0 .../time_filter.stories.storyshot | 0 .../__examples__/time_filter.stories.tsx | 0 .../time_filter/components/index.tsx | 0 .../time_filter/components/time_filter.tsx | 0 .../renderers/time_filter/index.tsx | 0 .../renderers/time_filter/time_filter.scss | 0 .../canvas_plugin_src/templates/index.ts | 0 .../templates/pitch_presentation.json | 0 .../templates/status_report.json | 0 .../templates/summary_report.json | 0 .../templates/theme_dark.json | 0 .../templates/theme_light.json | 0 .../extended_template.stories.storyshot | 0 .../simple_template.stories.storyshot | 0 .../extended_template.stories.tsx | 0 .../__examples__/simple_template.stories.tsx | 0 .../axis_config/extended_template.tsx | 0 .../uis/arguments/axis_config/index.ts | 0 .../arguments/axis_config/simple_template.tsx | 0 .../datacolumn/__tests__/get_form_object.js | 0 .../arguments/datacolumn/get_form_object.js | 0 .../uis/arguments/datacolumn/index.js | 0 .../datacolumn/simple_math_function.js | 0 .../date_format.stories.storyshot | 0 .../__examples__/date_format.stories.tsx | 0 .../uis/arguments/date_format/date_format.tsx | 0 .../uis/arguments/date_format/index.ts | 0 .../uis/arguments/filter_group.js | 0 .../uis/arguments/image_upload/forms/file.js | 0 .../uis/arguments/image_upload/forms/index.js | 0 .../uis/arguments/image_upload/forms/link.js | 0 .../arguments/image_upload/image_upload.scss | 0 .../uis/arguments/image_upload/index.js | 0 .../canvas_plugin_src/uis/arguments/index.ts | 0 .../canvas_plugin_src/uis/arguments/number.js | 0 .../number_format.stories.storyshot | 0 .../__examples__/number_format.stories.tsx | 0 .../uis/arguments/number_format/index.ts | 0 .../arguments/number_format/number_format.tsx | 0 .../uis/arguments/palette.js | 0 .../uis/arguments/percentage.js | 0 .../canvas_plugin_src/uis/arguments/range.js | 0 .../canvas_plugin_src/uis/arguments/select.js | 0 .../canvas_plugin_src/uis/arguments/shape.js | 0 .../canvas_plugin_src/uis/arguments/string.js | 0 .../uis/arguments/textarea.js | 0 .../canvas_plugin_src/uis/arguments/toggle.js | 0 .../uis/datasources/demodata.js | 0 .../uis/datasources/esdocs.js | 0 .../uis/datasources/essql.js | 0 .../uis/datasources/index.js | 0 .../uis/datasources/timelion.js | 0 .../canvas_plugin_src/uis/models/index.js | 0 .../canvas_plugin_src/uis/models/math.js | 0 .../uis/models/point_series.js | 0 .../canvas_plugin_src/uis/tags/index.ts | 0 .../uis/tags/presentation.ts | 0 .../canvas_plugin_src/uis/tags/report.ts | 0 .../uis/transforms/formatdate.ts | 0 .../uis/transforms/formatnumber.ts | 0 .../canvas_plugin_src/uis/transforms/index.js | 0 .../uis/transforms/rounddate.ts | 0 .../canvas_plugin_src/uis/transforms/sort.js | 0 .../uis/views/dropdownControl.js | 0 .../canvas_plugin_src/uis/views/getCell.js | 0 .../canvas_plugin_src/uis/views/image.js | 0 .../canvas_plugin_src/uis/views/index.ts | 0 .../canvas_plugin_src/uis/views/markdown.js | 0 .../canvas_plugin_src/uis/views/metric.ts | 0 .../canvas/canvas_plugin_src/uis/views/pie.js | 0 .../canvas_plugin_src/uis/views/plot.js | 0 .../canvas_plugin_src/uis/views/progress.js | 0 .../canvas_plugin_src/uis/views/render.js | 0 .../uis/views/repeatImage.js | 0 .../uis/views/revealImage.js | 0 .../canvas_plugin_src/uis/views/shape.js | 0 .../canvas_plugin_src/uis/views/table.js | 0 .../uis/views/timefilterControl.js | 0 .../canvas/common/lib/autocomplete.test.ts | 0 .../plugins/canvas/common/lib/autocomplete.ts | 2 +- .../plugins/canvas/common/lib/constants.ts | 0 .../canvas/common/lib/datatable/index.js | 0 .../canvas/common/lib/datatable/query.js | 0 .../plugins/canvas/common/lib/dataurl.test.ts | 0 .../plugins/canvas/common/lib/dataurl.ts | 0 .../plugins/canvas/common/lib/errors.js | 0 .../plugins/canvas/common/lib/errors.test.js | 0 .../common/lib/expression_form_handlers.js | 0 .../lib/expression_form_handlers.test.js | 0 .../plugins/canvas/common/lib/fetch.test.ts | 0 .../plugins/canvas/common/lib/fetch.ts | 0 .../plugins/canvas/common/lib/fonts.ts | 2 +- .../common/lib/get_colors_from_palette.js | 0 .../lib/get_colors_from_palette.test.js | 0 .../canvas/common/lib/get_field_type.test.ts | 0 .../canvas/common/lib/get_field_type.ts | 0 .../canvas/common}/lib/get_id.ts | 0 .../canvas/common/lib/get_legend_config.js | 0 .../common/lib/get_legend_config.test.js | 0 .../plugins/canvas/common/lib/handlebars.js | 0 .../canvas/common/lib/handlebars.test.js | 0 .../canvas/common/lib/hex_to_rgb.test.ts | 0 .../plugins/canvas/common/lib/hex_to_rgb.ts | 0 .../plugins/canvas/common/lib/httpurl.test.ts | 0 .../plugins/canvas/common/lib/httpurl.ts | 0 .../plugins/canvas/common/lib/index.ts | 0 .../canvas/common/lib/missing_asset.js | 0 .../plugins/canvas/common/lib/palettes.js | 0 .../common/lib/pivot_object_array.test.ts | 0 .../canvas/common/lib/pivot_object_array.ts | 0 .../canvas/common/lib/resolve_dataurl.js | 0 .../canvas/common/lib/resolve_dataurl.test.js | 0 .../plugins/canvas/common/lib/time_units.ts | 0 .../canvas/common/lib/unquote_string.test.ts | 0 .../canvas/common/lib/unquote_string.ts | 0 .../plugins/canvas/common/lib/url.js | 0 .../plugins/canvas/common/lib/url.test.js | 0 .../plugins/canvas/i18n/README.md | 0 .../plugins/canvas/i18n/capabilities.ts | 0 .../plugins/canvas/i18n/components.ts | 0 .../plugins/canvas/i18n/constants.ts | 0 .../canvas/i18n/elements/apply_strings.ts | 0 .../i18n/elements/element_strings.test.ts | 2 +- .../canvas/i18n/elements/element_strings.ts | 0 .../plugins/canvas/i18n/elements/index.ts | 0 .../plugins/canvas/i18n/errors.ts | 0 .../plugins/canvas/i18n/expression_types.ts | 0 .../plugins/canvas/i18n/functions/dict/all.ts | 0 .../i18n/functions/dict/alter_column.ts | 0 .../plugins/canvas/i18n/functions/dict/any.ts | 0 .../plugins/canvas/i18n/functions/dict/as.ts | 0 .../canvas/i18n/functions/dict/asset.ts | 0 .../canvas/i18n/functions/dict/axis_config.ts | 0 .../canvas/i18n/functions/dict/case.ts | 0 .../canvas/i18n/functions/dict/clear.ts | 0 .../canvas/i18n/functions/dict/columns.ts | 0 .../canvas/i18n/functions/dict/compare.ts | 0 .../i18n/functions/dict/container_style.ts | 0 .../canvas/i18n/functions/dict/context.ts | 0 .../plugins/canvas/i18n/functions/dict/csv.ts | 0 .../canvas/i18n/functions/dict/date.ts | 0 .../canvas/i18n/functions/dict/demodata.ts | 0 .../plugins/canvas/i18n/functions/dict/do.ts | 0 .../i18n/functions/dict/dropdown_control.ts | 0 .../plugins/canvas/i18n/functions/dict/eq.ts | 0 .../canvas/i18n/functions/dict/escount.ts | 0 .../canvas/i18n/functions/dict/esdocs.ts | 0 .../canvas/i18n/functions/dict/essql.ts | 0 .../canvas/i18n/functions/dict/exactly.ts | 0 .../canvas/i18n/functions/dict/filterrows.ts | 0 .../canvas/i18n/functions/dict/filters.ts | 0 .../canvas/i18n/functions/dict/formatdate.ts | 0 .../i18n/functions/dict/formatnumber.ts | 0 .../canvas/i18n/functions/dict/get_cell.ts | 0 .../plugins/canvas/i18n/functions/dict/gt.ts | 0 .../plugins/canvas/i18n/functions/dict/gte.ts | 0 .../canvas/i18n/functions/dict/head.ts | 0 .../plugins/canvas/i18n/functions/dict/if.ts | 0 .../canvas/i18n/functions/dict/image.ts | 0 .../canvas/i18n/functions/dict/join_rows.ts | 0 .../canvas/i18n/functions/dict/location.ts | 0 .../plugins/canvas/i18n/functions/dict/lt.ts | 0 .../plugins/canvas/i18n/functions/dict/lte.ts | 0 .../canvas/i18n/functions/dict/map_center.ts | 0 .../canvas/i18n/functions/dict/map_column.ts | 0 .../canvas/i18n/functions/dict/markdown.ts | 0 .../canvas/i18n/functions/dict/math.ts | 0 .../canvas/i18n/functions/dict/metric.ts | 0 .../plugins/canvas/i18n/functions/dict/neq.ts | 0 .../canvas/i18n/functions/dict/palette.ts | 0 .../plugins/canvas/i18n/functions/dict/pie.ts | 0 .../canvas/i18n/functions/dict/plot.ts | 0 .../plugins/canvas/i18n/functions/dict/ply.ts | 0 .../canvas/i18n/functions/dict/pointseries.ts | 0 .../canvas/i18n/functions/dict/progress.ts | 0 .../canvas/i18n/functions/dict/render.ts | 0 .../i18n/functions/dict/repeat_image.ts | 0 .../canvas/i18n/functions/dict/replace.ts | 0 .../i18n/functions/dict/reveal_image.ts | 0 .../canvas/i18n/functions/dict/rounddate.ts | 0 .../canvas/i18n/functions/dict/row_count.ts | 0 .../canvas/i18n/functions/dict/saved_lens.ts | 0 .../canvas/i18n/functions/dict/saved_map.ts | 0 .../i18n/functions/dict/saved_search.ts | 0 .../functions/dict/saved_visualization.ts | 0 .../i18n/functions/dict/series_style.ts | 0 .../canvas/i18n/functions/dict/shape.ts | 0 .../canvas/i18n/functions/dict/sort.ts | 0 .../i18n/functions/dict/static_column.ts | 0 .../canvas/i18n/functions/dict/string.ts | 0 .../canvas/i18n/functions/dict/switch.ts | 0 .../canvas/i18n/functions/dict/table.ts | 0 .../canvas/i18n/functions/dict/tail.ts | 0 .../canvas/i18n/functions/dict/time_range.ts | 0 .../canvas/i18n/functions/dict/timefilter.ts | 0 .../i18n/functions/dict/timefilter_control.ts | 0 .../canvas/i18n/functions/dict/timelion.ts | 0 .../plugins/canvas/i18n/functions/dict/to.ts | 0 .../canvas/i18n/functions/dict/urlparam.ts | 0 .../canvas/i18n/functions/function_errors.ts | 0 .../canvas/i18n/functions/function_help.ts | 0 .../plugins/canvas/i18n/functions/index.ts | 0 x-pack/plugins/canvas/i18n/index.ts | 14 +++- .../plugins/canvas/i18n/renderers.ts | 0 .../plugins/canvas/i18n/shortcuts.ts | 0 .../{legacy => }/plugins/canvas/i18n/tags.ts | 0 .../canvas/i18n/templates/apply_strings.ts | 0 .../plugins/canvas/i18n/templates/index.ts | 0 .../i18n/templates/template_strings.test.ts | 0 .../canvas/i18n/templates/template_strings.ts | 0 .../plugins/canvas/i18n/transitions.ts | 0 x-pack/{legacy => }/plugins/canvas/i18n/ui.ts | 0 .../{legacy => }/plugins/canvas/i18n/units.ts | 0 .../plugins/canvas/images/canvas.png | Bin .../plugins/canvas/images/canvas.svg | 0 .../plugins/canvas/images/canvas_blank.svg | 0 .../plugins/canvas/images/icon_black.svg | 0 .../plugins/canvas/images/logo.gif | Bin .../plugins/canvas/public/__tests__/setup.js | 0 .../plugins/canvas/public/application.tsx | 6 +- .../__snapshots__/export_app.test.tsx.snap | 0 .../export/__tests__/export_app.test.tsx | 0 .../public/apps/export/export/export_app.js | 0 .../public/apps/export/export/export_app.scss | 0 .../canvas/public/apps/export/export/index.js | 0 .../public/apps/export/export/load_workpad.js | 0 .../canvas/public/apps/export/index.js | 0 .../canvas/public/apps/export/routes.js | 0 .../public/apps/home/home_app/home_app.js | 0 .../public/apps/home/home_app/home_app.scss | 0 .../canvas/public/apps/home/home_app/index.js | 0 .../plugins/canvas/public/apps/home/index.js | 0 .../plugins/canvas/public/apps/home/routes.js | 0 .../plugins/canvas/public/apps/index.js | 0 .../canvas/public/apps/workpad/index.js | 0 .../canvas/public/apps/workpad/routes.js | 0 .../public/apps/workpad/workpad_app/index.js | 0 .../apps/workpad/workpad_app/load_workpad.js | 0 .../apps/workpad/workpad_app/workpad_app.js | 0 .../apps/workpad/workpad_app/workpad_app.scss | 0 .../workpad_app/workpad_telemetry.test.tsx | 0 .../workpad/workpad_app/workpad_telemetry.tsx | 0 .../alignment_guide/alignment_guide.js | 0 .../alignment_guide/alignment_guide.scss | 0 .../components/alignment_guide/index.js | 0 .../canvas/public/components/app/app.js | 0 .../canvas/public/components/app/index.js | 0 .../components/app/track_route_change.js | 0 .../public/components/arg_add/arg_add.js | 0 .../public/components/arg_add/arg_add.scss | 0 .../canvas/public/components/arg_add/index.js | 0 .../arg_add_popover/arg_add_popover.scss | 0 .../arg_add_popover/arg_add_popover.tsx | 0 .../components/arg_add_popover/index.ts | 0 .../components/arg_form/advanced_failure.js | 0 .../public/components/arg_form/arg_form.js | 0 .../public/components/arg_form/arg_form.scss | 0 .../public/components/arg_form/arg_label.js | 0 .../components/arg_form/arg_simple_form.tsx | 0 .../components/arg_form/arg_template_form.js | 0 .../public/components/arg_form/index.js | 0 .../components/arg_form/pending_arg_value.js | 0 .../components/arg_form/simple_failure.tsx | 0 .../__snapshots__/asset.examples.storyshot | 0 .../asset_manager.examples.storyshot | 0 .../asset_manager.stories.storyshot | 0 .../__examples__/asset.examples.tsx | 0 .../__examples__/asset_manager.stories.tsx | 0 .../public/components/asset_manager/asset.tsx | 0 .../asset_manager/asset_manager.scss | 0 .../asset_manager/asset_manager.tsx | 0 .../components/asset_manager/asset_modal.tsx | 0 .../public/components/asset_manager/index.ts | 2 +- .../components/asset_picker/asset_picker.scss | 0 .../components/asset_picker/asset_picker.tsx | 0 .../public/components/asset_picker/index.ts | 0 .../components/autocomplete/autocomplete.js | 0 .../components/autocomplete/autocomplete.scss | 0 .../public/components/autocomplete/index.js | 0 .../border_connection/border_connection.js | 0 .../border_connection/border_connection.scss | 0 .../components/border_connection/index.js | 0 .../border_resize_handle.js | 0 .../border_resize_handle.scss | 0 .../components/border_resize_handle/index.js | 0 .../components/clipboard/clipboard.scss | 0 .../public/components/clipboard/clipboard.tsx | 0 .../public/components/clipboard/index.ts | 0 .../__snapshots__/color_dot.stories.storyshot | 0 .../__examples__/color_dot.stories.tsx | 0 .../components/color_dot/color_dot.scss | 0 .../public/components/color_dot/color_dot.tsx | 0 .../public/components/color_dot/index.ts | 0 .../color_manager.stories.storyshot | 0 .../__examples__/color_manager.stories.tsx | 0 .../color_manager/color_manager.tsx | 0 .../public/components/color_manager/index.ts | 0 .../color_palette.stories.storyshot | 0 .../__examples__/color_palette.stories.tsx | 0 .../color_palette/color_palette.scss | 0 .../color_palette/color_palette.tsx | 0 .../public/components/color_palette/index.ts | 0 .../color_picker.stories.storyshot | 0 .../__examples__/color_picker.stories.tsx | 0 .../components/color_picker/color_picker.tsx | 0 .../public/components/color_picker/index.ts | 0 .../color_picker_popover.stories.storyshot | 0 .../color_picker_popover.stories.tsx | 0 .../color_picker_popover.scss | 0 .../color_picker_popover.tsx | 0 .../components/color_picker_popover/index.ts | 0 .../confirm_modal/confirm_modal.tsx | 0 .../public/components/confirm_modal/index.ts | 0 .../custom_element_modal.examples.storyshot | 0 .../custom_element_modal.examples.tsx | 0 .../custom_element_modal.scss | 0 .../custom_element_modal.tsx | 0 .../components/custom_element_modal/index.tsx | 0 .../components/datasource/datasource.js | 0 .../components/datasource/datasource.scss | 0 .../datasource/datasource_component.js | 0 .../datasource_preview/datasource_preview.js | 0 .../datasource_preview.scss | 0 .../datasource/datasource_preview/index.js | 0 .../datasource/datasource_selector.js | 0 .../public/components/datasource/index.js | 0 .../components/datasource/no_datasource.js | 0 .../public/components/datatable/datatable.js | 0 .../components/datatable/datatable.scss | 0 .../public/components/datatable/index.js | 0 .../__snapshots__/debug.examples.storyshot | 0 .../debug/__examples__/debug.examples.tsx | 0 .../components/debug/__examples__/helpers.tsx | 0 .../canvas/public/components/debug/debug.scss | 0 .../canvas/public/components/debug/debug.tsx | 0 .../canvas/public/components/debug/index.tsx | 0 .../components/dom_preview/dom_preview.js | 0 .../components/dom_preview/dom_preview.scss | 0 .../public/components/dom_preview/index.js | 0 .../download/__tests__/download.test.tsx | 0 .../public/components/download/download.tsx | 0 .../public/components/download/index.ts | 0 .../dragbox_annotation/dragbox_annotation.js | 0 .../dragbox_annotation.scss | 0 .../components/dragbox_annotation/index.js | 0 .../element_card.stories.storyshot | 0 .../element_controls.examples.storyshot | 0 .../__examples__/element_card.stories.tsx | 0 .../components/element_card/element_card.scss | 0 .../components/element_card/element_card.tsx | 0 .../public/components/element_card/index.tsx | 0 .../element_config/element_config.js | 0 .../public/components/element_config/index.js | 0 .../element_content/element_content.js | 0 .../element_content/element_content.scss | 0 .../components/element_content/index.js | 2 +- .../element_content/invalid_element_type.js | 0 .../element_content/invalid_expression.js | 0 .../element_share_container.js | 0 .../element_share_container/index.js | 0 .../element_wrapper/element_wrapper.js | 0 .../components/element_wrapper/index.js | 0 .../element_wrapper/lib/handlers.js | 0 .../components/embeddable_flyout/flyout.tsx | 4 +- .../components/embeddable_flyout/index.tsx | 2 +- .../components/enhance/error_boundary.tsx | 0 .../components/enhance/stateful_prop.js | 0 .../canvas/public/components/error/error.js | 0 .../canvas/public/components/error/index.js | 0 .../public/components/error/show_debugging.js | 0 .../es_field_select/es_field_select.js | 0 .../components/es_field_select/index.js | 0 .../es_fields_select/es_fields_select.js | 0 .../components/es_fields_select/index.js | 0 .../es_index_select/es_index_select.js | 0 .../components/es_index_select/index.js | 0 .../expression/element_not_selected.js | 0 .../components/expression/expression.js | 0 .../components/expression/expression.scss | 0 .../public/components/expression/index.js | 2 +- .../expression_input.examples.storyshot | 0 .../expression_input.examples.tsx | 0 .../expression_input/expression_input.tsx | 4 +- .../components/expression_input/index.js | 0 .../components/expression_input/reference.ts | 2 +- .../file_upload.stories.storyshot | 0 .../file_upload/file_upload.stories.tsx | 0 .../components/file_upload/file_upload.tsx | 0 .../font_picker.stories.storyshot | 0 .../font_picker/font_picker.stories.tsx | 0 .../components/font_picker/font_picker.tsx | 0 .../public/components/font_picker/index.js | 0 .../format_select/format_select.tsx | 0 .../public/components/format_select/index.ts | 0 .../components/fullscreen/fullscreen.js | 0 .../components/fullscreen/fullscreen.scss | 0 .../public/components/fullscreen/index.js | 0 .../components/function_form/function_form.js | 0 .../function_form/function_form.scss | 0 .../function_form/function_form_component.js | 0 .../function_form_context_error.tsx | 0 .../function_form_context_pending.js | 0 .../function_form/function_unknown.tsx | 0 .../public/components/function_form/index.js | 0 .../function_form_list/function_form_list.js | 0 .../components/function_form_list/index.js | 0 .../public/components/help_menu/help_menu.js | 0 .../public/components/help_menu/index.js | 0 .../hover_annotation/hover_annotation.js | 0 .../hover_annotation/hover_annotation.scss | 0 .../components/hover_annotation/index.js | 0 .../__snapshots__/item_grid.stories.storyshot | 0 .../__examples__/item_grid.stories.tsx | 0 .../public/components/item_grid/index.ts | 0 .../public/components/item_grid/item_grid.tsx | 0 .../keyboard_shortcuts_doc.stories.storyshot | 0 .../keyboard_shortcuts_doc.stories.tsx | 0 .../keyboard_shortcuts_doc/index.ts | 0 .../keyboard_shortcuts_doc.tsx | 0 .../canvas/public/components/link/index.js | 0 .../canvas/public/components/link/link.js | 0 .../components/loading/__tests__/loading.js | 0 .../canvas/public/components/loading/index.ts | 0 .../public/components/loading/loading.scss | 0 .../public/components/loading/loading.tsx | 0 .../canvas/public/components/navbar/index.js | 0 .../canvas/public/components/navbar/navbar.js | 0 .../public/components/navbar/navbar.scss | 0 .../public/components/page_config/index.js | 0 .../components/page_config/page_config.js | 0 .../public/components/page_manager/index.js | 0 .../components/page_manager/page_manager.js | 0 .../components/page_manager/page_manager.scss | 0 .../public/components/page_preview/index.js | 0 .../components/page_preview/page_controls.js | 0 .../components/page_preview/page_preview.js | 0 .../public/components/paginate/index.js | 0 .../public/components/paginate/paginate.js | 0 .../public/components/palette_picker/index.js | 0 .../palette_picker/palette_picker.js | 0 .../palette_picker/palette_picker.scss | 0 .../public/components/palette_swatch/index.js | 0 .../palette_swatch/palette_swatch.js | 0 .../palette_swatch/palette_swatch.scss | 0 .../canvas/public/components/popover/index.ts | 0 .../public/components/popover/popover.tsx | 0 .../public/components/positionable/index.js | 0 .../components/positionable/positionable.js | 0 .../components/positionable/positionable.scss | 0 .../public/components/render_to_dom/index.js | 0 .../components/render_to_dom/render_to_dom.js | 0 .../public/components/render_with_fn/index.js | 2 +- .../components/render_with_fn/lib/handlers.js | 0 .../render_with_fn/render_with_fn.js | 0 .../components/rotation_handle/index.js | 0 .../rotation_handle/rotation_handle.js | 0 .../rotation_handle/rotation_handle.scss | 0 .../components/router/canvas_loading.js | 0 .../canvas/public/components/router/index.ts | 0 .../canvas/public/components/router/router.js | 0 .../element_controls.stories.storyshot | 0 .../element_grid.stories.storyshot | 0 .../saved_elements_modal.stories.storyshot | 0 .../__examples__/element_controls.stories.tsx | 0 .../__examples__/element_grid.stories.tsx | 0 .../__examples__/fixtures/test_elements.tsx | 0 .../saved_elements_modal.stories.tsx | 0 .../saved_elements_modal/element_controls.tsx | 0 .../saved_elements_modal/element_grid.tsx | 0 .../components/saved_elements_modal/index.ts | 2 +- .../saved_elements_modal.tsx | 0 .../shape_picker.stories.storyshot | 0 .../__examples__/shape_picker.stories.tsx | 0 .../public/components/shape_picker/index.ts | 0 .../components/shape_picker/shape_picker.scss | 0 .../components/shape_picker/shape_picker.tsx | 0 .../shape_picker_popover.stories.storyshot | 0 .../shape_picker_popover.stories.tsx | 0 .../components/shape_picker_popover/index.tsx | 0 .../shape_picker_popover.tsx | 0 .../shape_preview.stories.storyshot | 0 .../__examples__/shape_preview.stories.tsx | 0 .../public/components/shape_preview/index.ts | 0 .../shape_preview/shape_preview.scss | 0 .../shape_preview/shape_preview.tsx | 0 .../group_settings.stories.storyshot | 0 .../multi_element_settings.stories.storyshot | 0 .../__examples__/group_settings.stories.tsx | 0 .../multi_element_settings.stories.tsx | 0 .../element_settings/element_settings.tsx | 0 .../sidebar/element_settings/index.tsx | 0 .../components/sidebar/global_config.tsx | 0 .../components/sidebar/group_settings.tsx | 0 .../public/components/sidebar/index.tsx | 0 .../sidebar/multi_element_settings.tsx | 0 .../public/components/sidebar/sidebar.scss | 0 .../public/components/sidebar/sidebar.tsx | 0 .../components/sidebar/sidebar_content.js | 0 .../components/sidebar/sidebar_section.js | 0 .../sidebar/sidebar_section_title.js | 0 .../sidebar_header.stories.storyshot | 0 .../__examples__/sidebar_header.stories.tsx | 0 .../public/components/sidebar_header/index.js | 0 .../sidebar_header/sidebar_header.scss | 0 .../sidebar_header/sidebar_header.tsx | 0 .../__snapshots__/tag.stories.storyshot | 0 .../tag/__examples__/tag.stories.tsx | 0 .../canvas/public/components/tag/index.tsx | 0 .../canvas/public/components/tag/tag.tsx | 0 .../__snapshots__/tag_list.stories.storyshot | 0 .../__examples__/tag_list.stories.tsx | 0 .../public/components/tag_list/index.tsx | 0 .../public/components/tag_list/tag_list.tsx | 0 .../text_style_picker/font_sizes.js | 0 .../components/text_style_picker/index.js | 0 .../text_style_picker/text_style_picker.js | 0 .../tool_tip_shortcut.stories.storyshot | 0 .../tool_tip_shortcut.stories.tsx | 0 .../components/tool_tip_shortcut/index.tsx | 0 .../tool_tip_shortcut/tool_tip_shortcut.tsx | 0 .../toolbar/__examples__/toolbar.stories.tsx | 0 .../canvas/public/components/toolbar/index.js | 0 .../public/components/toolbar/toolbar.scss | 0 .../public/components/toolbar/toolbar.tsx | 0 .../public/components/toolbar/tray/index.ts | 0 .../public/components/toolbar/tray/tray.scss | 0 .../public/components/toolbar/tray/tray.tsx | 0 .../components/tooltip_annotation/index.js | 0 .../tooltip_annotation/tooltip_annotation.js | 0 .../tooltip_annotation.scss | 0 .../public/components/tooltip_icon/index.ts | 0 .../components/tooltip_icon/tooltip_icon.tsx | 0 .../canvas/public/components/workpad/index.js | 0 .../public/components/workpad/workpad.js | 0 .../public/components/workpad/workpad.scss | 0 .../components/workpad_color_picker/index.ts | 0 .../workpad_color_picker.tsx | 0 .../public/components/workpad_config/index.js | 0 .../workpad_config/workpad_config.js | 0 .../edit_menu.examples.storyshot | 0 .../__examples__/edit_menu.examples.tsx | 0 .../workpad_header/edit_menu/edit_menu.tsx | 0 .../workpad_header/edit_menu/index.ts | 0 .../element_menu.examples.storyshot | 0 .../__examples__/element_menu.examples.tsx | 0 .../element_menu/element_menu.scss | 0 .../element_menu/element_menu.tsx | 0 .../workpad_header/element_menu/index.tsx | 2 +- .../fullscreen_control/fullscreen_control.tsx | 0 .../fullscreen_control/index.js | 0 .../components/workpad_header/index.tsx | 0 .../workpad_header/refresh_control/index.ts | 0 .../refresh_control/refresh_control.tsx | 0 .../__snapshots__/pdf_panel.stories.storyshot | 0 .../share_menu.examples.storyshot | 0 .../__examples__/pdf_panel.stories.tsx | 0 .../__examples__/share_menu.examples.tsx | 0 .../share_website_flyout.stories.tsx | 0 .../workpad_header/share_menu/flyout/index.ts | 2 +- .../share_menu/flyout/runtime_step.tsx | 0 .../flyout/share_website_flyout.tsx | 0 .../share_menu/flyout/snippets_step.tsx | 0 .../share_menu/flyout/workpad_step.tsx | 0 .../workpad_header/share_menu/index.ts | 4 +- .../workpad_header/share_menu/pdf_panel.tsx | 0 .../workpad_header/share_menu/share_menu.scss | 0 .../workpad_header/share_menu/share_menu.tsx | 0 .../workpad_header/share_menu/utils.test.ts | 0 .../workpad_header/share_menu/utils.ts | 2 +- .../__snapshots__/view_menu.stories.storyshot | 0 .../__examples__/view_menu.stories.tsx | 0 .../view_menu/auto_refresh_controls.tsx | 0 .../view_menu/custom_interval.tsx | 0 .../workpad_header/view_menu/index.ts | 2 +- .../view_menu/kiosk_controls.tsx | 0 .../view_menu/lib/get_fit_zoom_scale.ts | 0 .../workpad_header/view_menu/view_menu.scss | 0 .../workpad_header/view_menu/view_menu.tsx | 0 .../workpad_header/workpad_header.tsx | 0 .../public/components/workpad_loader/index.js | 2 +- .../workpad_loader/upload_workpad.js | 0 .../workpad_loader/workpad_create.js | 0 .../workpad_loader/workpad_dropzone/index.js | 0 .../workpad_dropzone/workpad_dropzone.js | 0 .../workpad_dropzone/workpad_dropzone.scss | 0 .../workpad_loader/workpad_loader.js | 0 .../workpad_loader/workpad_loader.scss | 0 .../workpad_loader/workpad_search.js | 0 .../components/workpad_manager/index.js | 0 .../workpad_manager/workpad_manager.js | 0 .../public/components/workpad_page/index.js | 0 .../workpad_page/integration_utils.js | 0 .../workpad_page/positioning_utils.ts | 0 .../components/workpad_page/prop_types.js | 0 .../public/components/workpad_page/utils.js | 0 .../event_handlers.js | 0 .../workpad_interactive_page/index.js | 0 .../interaction_boundary.tsx | 0 .../interactive_workpad_page.js | 0 .../workpad_interactive_page.scss | 0 .../components/workpad_page/workpad_page.scss | 0 .../workpad_page/workpad_static_page/index.js | 0 .../static_workpad_page.js | 0 .../workpad_static_page.scss | 0 .../components/workpad_shortcuts/index.tsx | 0 .../workpad_shortcuts/workpad_shortcuts.tsx | 0 .../components/workpad_templates/index.js | 2 +- .../workpad_templates/workpad_templates.js | 0 .../canvas/public/expression_types/arg.js | 0 .../public/expression_types/arg_type.js | 0 .../expression_types/arg_types/color.js | 0 .../extended_template.examples.storyshot | 0 .../simple_template.examples.storyshot | 0 .../extended_template.examples.tsx | 0 .../__examples__/simple_template.examples.tsx | 0 .../container_style/appearance_form.tsx | 0 .../arg_types/container_style/border_form.tsx | 0 .../container_style/extended_template.tsx | 0 .../arg_types/container_style/index.ts | 0 .../container_style/simple_template.tsx | 0 .../public/expression_types/arg_types/font.js | 0 .../expression_types/arg_types/index.js | 0 .../extended_template.examples.storyshot | 0 .../simple_template.examples.storyshot | 0 .../extended_template.examples.tsx | 0 .../__examples__/simple_template.examples.tsx | 0 .../series_style/extended_template.tsx | 0 .../arg_types/series_style/index.ts | 0 .../series_style/simple_template.tsx | 0 .../public/expression_types/base_form.js | 0 .../public/expression_types/datasource.js | 0 .../public/expression_types/function_form.js | 0 .../canvas/public/expression_types/index.js | 0 .../canvas/public/expression_types/model.js | 0 .../public/expression_types/transform.js | 0 .../canvas/public/expression_types/view.js | 0 .../canvas/public/feature_catalogue_entry.ts | 2 +- .../public/functions/__tests__/asset.js | 0 .../plugins/canvas/public/functions/asset.ts | 0 .../canvas/public/functions/filters.ts | 0 .../plugins/canvas/public/functions/index.ts | 0 .../canvas/public/functions/timelion.ts | 0 .../plugins/canvas/public/functions/to.ts | 0 .../plugins/canvas/public/icon.svg | 0 x-pack/plugins/canvas/public/index.ts | 12 +++- .../lib/__tests__/find_expression_type.js | 0 .../lib/__tests__/get_pretty_shortcut.test.ts | 0 .../public/lib/__tests__/history_provider.js | 0 .../public/lib/__tests__/modify_path.js | 0 .../lib/__tests__/readable_color.test.ts | 0 .../public/lib/__tests__/resolved_arg.js | 0 .../lib/__tests__/time_interval.test.ts | 0 .../__fixtures__/typescript/typespec_tests.ts | 0 .../canvas/public/lib/aeroelastic/common.js | 0 .../public/lib/aeroelastic/functional.js | 0 .../canvas/public/lib/aeroelastic/geometry.js | 0 .../canvas/public/lib/aeroelastic/gestures.js | 0 .../canvas/public/lib/aeroelastic/index.d.ts | 0 .../canvas/public/lib/aeroelastic/layout.js | 0 .../lib/aeroelastic/layout_functions.js | 0 .../canvas/public/lib/aeroelastic/matrix.ts | 0 .../canvas/public/lib/aeroelastic/matrix2d.ts | 0 .../canvas/public/lib/aeroelastic/select.ts | 0 .../canvas/public/lib/aeroelastic/store.ts | 0 .../public/lib/aeroelastic/tsconfig.json | 2 +- .../canvas/public/lib/app_handler_creators.ts | 0 .../plugins/canvas/public/lib/app_state.ts | 0 .../plugins/canvas/public/lib/arg_helpers.js | 0 .../plugins/canvas/public/lib/breadcrumbs.ts | 2 +- .../canvas/public/lib/build_bool_array.js | 0 .../lib/build_embeddable_filters.test.ts | 0 .../public/lib/build_embeddable_filters.ts | 6 +- .../canvas/public/lib/clipboard.test.ts | 4 +- .../plugins/canvas/public/lib/clipboard.ts | 2 +- .../canvas/public/lib/clone_subgraphs.js | 0 .../public/lib/custom_element_service.ts | 0 .../plugins/canvas/public/lib/doc_title.js | 0 .../canvas/public/lib/documentation_links.ts | 0 .../plugins/canvas/public/lib/dom.ts | 0 .../canvas/public/lib/download_workpad.ts | 0 .../plugins/canvas/public/lib/elastic_logo.ts | 0 .../canvas/public/lib/elastic_outline.js | 0 .../plugins/canvas/public/lib/element.ts | 0 .../public/lib/element_handler_creators.ts | 0 .../canvas/public/lib/elements_registry.js | 0 .../plugins/canvas/public/lib/es_service.ts | 0 .../canvas/public/lib/extract_search.js | 0 .../plugins/canvas/public/lib/filters.js | 0 .../canvas/public/lib/find_existing_asset.js | 0 .../canvas/public/lib/find_expression_type.js | 0 .../canvas/public/lib/flatten_panel_tree.ts | 0 .../plugins/canvas/public/lib/fullscreen.js | 0 .../canvas/public/lib/get_client_platform.ts | 0 .../canvas/public/lib/get_es_filter.js | 0 .../canvas/public/lib/get_id.ts} | 11 ++- .../canvas/public/lib/get_pretty_shortcut.ts | 0 .../canvas/public/lib/get_tags_filter.tsx | 0 .../plugins/canvas/public/lib/get_window.ts | 0 .../canvas/public/lib/history_provider.js | 0 .../canvas/public/lib/is_text_input.ts | 0 .../plugins/canvas/public/lib/keymap.ts | 0 .../canvas/public/lib/legend_options.js | 0 .../public/lib/load_expression_types.js | 0 .../canvas/public/lib/load_transitions.js | 0 .../canvas/public/lib/loading_indicator.ts | 0 .../plugins/canvas/public/lib/modify_path.js | 0 .../plugins/canvas/public/lib/modify_url.ts | 0 .../canvas/public/lib/monaco_language_def.ts | 0 .../public/lib/parse_single_function_chain.js | 0 .../canvas/public/lib/readable_color.ts | 0 .../plugins/canvas/public/lib/resolved_arg.js | 0 .../canvas/public/lib/router_provider.js | 0 .../canvas/public/lib/run_interpreter.ts | 0 .../canvas/public/lib/shortcut_manager.js | 0 .../public/lib/sync_filter_expression.ts | 0 .../plugins/canvas/public/lib/tag.ts | 0 .../canvas/public/lib/tags_registry.ts | 0 .../plugins/canvas/public/lib/template.js | 0 .../lib/template_from_react_component.tsx | 0 .../canvas/public/lib/templates_registry.js | 0 .../canvas/public/lib/time_duration.ts | 0 .../canvas/public/lib/time_interval.ts | 0 .../canvas/public/lib/transitions_registry.js | 0 .../plugins/canvas/public/lib/ui_metric.ts | 0 .../canvas/public/lib/window_error_handler.js | 0 .../canvas/public/lib/workpad_service.js | 0 .../plugins/canvas/public/plugin.tsx | 22 +++--- .../plugins/canvas/public/plugin_api.ts | 2 +- .../plugins/canvas/public/registries.ts | 0 .../plugins/canvas/public/services/index.ts | 2 +- .../plugins/canvas/public/services/notify.ts | 4 +- .../canvas/public/services/platform.ts | 0 .../__tests__/elements.get_sibling_context.js | 0 .../canvas/public/state/actions/app.js | 0 .../canvas/public/state/actions/assets.js | 0 .../canvas/public/state/actions/elements.js | 0 .../canvas/public/state/actions/embeddable.ts | 0 .../canvas/public/state/actions/history.js | 0 .../canvas/public/state/actions/pages.js | 0 .../public/state/actions/resolved_args.ts | 0 .../canvas/public/state/actions/transient.js | 0 .../canvas/public/state/actions/workpad.js | 0 .../plugins/canvas/public/state/defaults.js | 0 .../canvas/public/state/initial_state.js | 0 .../middleware/__tests__/in_flight.test.ts | 0 .../__tests__/workpad_autoplay.test.ts | 0 .../__tests__/workpad_refresh.test.ts | 1 - .../public/state/middleware/app_ready.js | 0 .../public/state/middleware/breadcrumbs.js | 0 .../public/state/middleware/element_stats.js | 0 .../public/state/middleware/es_persist.js | 0 .../public/state/middleware/fullscreen.js | 0 .../canvas/public/state/middleware/history.js | 0 .../public/state/middleware/in_flight.ts | 0 .../canvas/public/state/middleware/index.js | 0 .../public/state/middleware/resolved_args.js | 0 .../state/middleware/workpad_autoplay.ts | 0 .../state/middleware/workpad_refresh.ts | 0 .../public/state/middleware/workpad_update.js | 0 .../state/reducers/__tests__/elements.js | 0 .../__tests__/fixtures/action_creator.js | 0 .../state/reducers/__tests__/resolved_args.js | 0 .../canvas/public/state/reducers/app.js | 0 .../canvas/public/state/reducers/assets.js | 0 .../canvas/public/state/reducers/elements.js | 0 .../public/state/reducers/embeddable.ts | 0 .../public/state/reducers/embeddables.test.ts | 0 .../canvas/public/state/reducers/history.js | 0 .../canvas/public/state/reducers/index.js | 0 .../canvas/public/state/reducers/pages.js | 0 .../public/state/reducers/resolved_args.js | 0 .../canvas/public/state/reducers/transient.js | 0 .../canvas/public/state/reducers/workpad.js | 0 .../selectors/__tests__/resolved_args.js | 0 .../state/selectors/__tests__/workpad.js | 0 .../canvas/public/state/selectors/app.ts | 0 .../canvas/public/state/selectors/assets.ts | 0 .../public/state/selectors/resolved_args.ts | 0 .../canvas/public/state/selectors/workpad.ts | 4 +- .../plugins/canvas/public/state/store.js | 0 .../plugins/canvas/public/store.ts | 2 +- .../plugins/canvas/public/style/hackery.scss | 0 .../plugins/canvas/public/style/index.scss | 0 .../plugins/canvas/public/style/main.scss | 0 .../canvas/public/transitions/fade/fade.scss | 0 .../canvas/public/transitions/fade/index.ts | 0 .../canvas/public/transitions/index.ts | 0 .../canvas/public/transitions/rotate/index.ts | 0 .../public/transitions/rotate/rotate.scss | 0 .../canvas/public/transitions/slide/index.ts | 0 .../public/transitions/slide/slide.scss | 0 .../canvas/public/transitions/transition.js | 0 .../canvas/public/transitions/zoom/index.ts | 0 .../canvas/public/transitions/zoom/zoom.scss | 0 .../plugins/canvas/scripts/_helpers.js | 10 +-- .../plugins/canvas/scripts/jest.js | 8 +-- .../plugins/canvas/scripts/kbn.js | 0 .../plugins/canvas/scripts/lint.js | 4 +- .../canvas/scripts/shareable_runtime.js | 0 .../plugins/canvas/scripts/storybook.js | 8 +-- .../plugins/canvas/scripts/storybook_new.js | 0 .../plugins/canvas/scripts/test.js | 0 .../plugins/canvas/scripts/test_browser.js | 0 .../plugins/canvas/scripts/test_common.js | 0 .../plugins/canvas/scripts/test_dev.js | 0 .../plugins/canvas/scripts/test_plugins.js | 0 .../plugins/canvas/scripts/test_server.js | 0 .../canvas/server/collectors/collector.ts | 2 +- .../collectors/workpad_collector.test.ts | 2 +- .../server/collectors/workpad_collector.ts | 2 +- .../routes/custom_elements/create.test.ts | 2 +- .../server/routes/custom_elements/create.ts | 7 +- .../custom_element_attributes.ts | 2 +- .../routes/custom_elements/delete.test.ts | 2 +- .../server/routes/custom_elements/delete.ts | 5 +- .../server/routes/custom_elements/find.ts | 5 +- .../server/routes/custom_elements/get.test.ts | 2 +- .../server/routes/custom_elements/get.ts | 5 +- .../routes/custom_elements/update.test.ts | 4 +- .../server/routes/custom_elements/update.ts | 5 +- .../server/routes/es_fields/es_fields.ts | 2 +- .../server/routes/shareables/download.ts | 4 +- .../server/routes/shareables/zip.test.ts | 4 +- .../canvas/server/routes/shareables/zip.ts | 4 +- .../server/routes/workpad/create.test.ts | 2 +- .../canvas/server/routes/workpad/create.ts | 9 +-- .../server/routes/workpad/delete.test.ts | 2 +- .../canvas/server/routes/workpad/delete.ts | 5 +- .../canvas/server/routes/workpad/find.ts | 5 +- .../canvas/server/routes/workpad/get.test.ts | 6 +- .../canvas/server/routes/workpad/get.ts | 5 +- .../server/routes/workpad/update.test.ts | 4 +- .../canvas/server/routes/workpad/update.ts | 2 +- .../routes/workpad/workpad_attributes.ts | 2 +- .../server/saved_objects/custom_element.ts | 2 +- .../canvas/server/saved_objects/workpad.ts | 2 +- .../canvas/server/setup_interpreter.ts | 2 +- .../canvas/shareable_runtime/README.md | 0 .../__mocks__/supported_renderers.js | 0 .../__snapshots__/shareable.test.tsx.snap | 0 .../api/__tests__/shareable.test.tsx | 0 .../canvas/shareable_runtime/api/index.ts | 0 .../shareable_runtime/api/shareable.tsx | 0 .../__snapshots__/canvas.examples.storyshot | 0 .../__snapshots__/page.examples.storyshot | 0 .../rendered_element.examples.storyshot | 0 .../__examples__/canvas.examples.tsx | 0 .../components/__examples__/page.examples.tsx | 0 .../rendered_element.examples.tsx | 0 .../__tests__/__snapshots__/app.test.tsx.snap | 0 .../components/__tests__/app.test.tsx | 0 .../components/__tests__/canvas.test.tsx | 0 .../components/__tests__/page.test.tsx | 0 .../shareable_runtime/components/app.tsx | 0 .../components/canvas.module.scss | 0 .../shareable_runtime/components/canvas.tsx | 0 .../footer.components.examples.storyshot | 0 .../__snapshots__/footer.examples.storyshot | 0 .../page_controls.examples.storyshot | 0 .../__snapshots__/scrubber.examples.storyshot | 0 .../__snapshots__/title.examples.storyshot | 0 .../footer/__examples__/footer.examples.tsx | 0 .../__examples__/page_controls.examples.tsx | 0 .../footer/__examples__/scrubber.examples.tsx | 0 .../footer/__examples__/title.examples.tsx | 0 .../footer/__tests__/footer.test.tsx | 0 .../footer/__tests__/page_controls.test.tsx | 0 .../footer/__tests__/page_preview.test.tsx | 0 .../footer/__tests__/scrubber.test.tsx | 0 .../footer/__tests__/title.test.tsx | 0 .../components/footer/footer.module.scss | 0 .../components/footer/footer.tsx | 0 .../components/footer/index.ts | 0 .../components/footer/page_controls.tsx | 0 .../footer/page_preview.module.scss | 0 .../components/footer/page_preview.tsx | 0 .../components/footer/scrubber.module.scss | 0 .../components/footer/scrubber.tsx | 0 .../autoplay_settings.examples.storyshot | 0 .../settings.components.examples.storyshot | 0 .../__snapshots__/settings.examples.storyshot | 0 .../toolbar_settings.examples.storyshot | 0 .../autoplay_settings.examples.tsx | 0 .../__examples__/settings.examples.tsx | 0 .../toolbar_settings.examples.tsx | 0 .../__snapshots__/settings.test.tsx.snap | 0 .../__tests__/autoplay_settings.test.tsx | 0 .../settings/__tests__/settings.test.tsx | 0 .../__tests__/toolbar_settings.test.tsx | 0 .../footer/settings/autoplay_settings.tsx | 0 .../components/footer/settings/index.ts | 0 .../components/footer/settings/settings.tsx | 0 .../footer/settings/toolbar_settings.tsx | 0 .../components/footer/title.tsx | 0 .../components/page.module.scss | 0 .../shareable_runtime/components/page.tsx | 0 .../components/rendered_element.module.scss | 0 .../components/rendered_element.tsx | 0 .../canvas/shareable_runtime/constants.d.ts | 0 .../canvas/shareable_runtime/constants.js | 4 +- .../shareable_runtime/constants_static.d.ts | 0 .../shareable_runtime/constants_static.js | 0 .../shareable_runtime/context/actions.ts | 0 .../canvas/shareable_runtime/context/index.ts | 0 .../shareable_runtime/context/reducer.ts | 0 .../shareable_runtime/context/state.tsx | 0 .../canvas/shareable_runtime/css_modules.d.ts | 0 .../canvas/shareable_runtime/index.html | 0 .../plugins/canvas/shareable_runtime/index.ts | 6 +- .../shareable_runtime/postcss.config.js | 0 .../supported_renderers.d.ts | 0 .../shareable_runtime/supported_renderers.js | 0 .../canvas/shareable_runtime/template.html | 0 .../canvas/shareable_runtime/test/context.tsx | 0 .../shareable_runtime/test/context_example.ts | 0 .../shareable_runtime/test/context_jest.ts | 0 .../canvas/shareable_runtime/test/index.ts | 0 .../shareable_runtime/test/interactions.ts | 0 .../shareable_runtime/test/selectors.ts | 0 .../canvas/shareable_runtime/test/utils.ts | 0 .../test/workpads/austin.json | 0 .../test/workpads/hello.json | 0 .../shareable_runtime/test/workpads/test.json | 0 .../plugins/canvas/shareable_runtime/types.ts | 0 .../shareable_runtime/webpack.config.js | 0 .../tasks/mocks/customElementService.js | 0 .../canvas/tasks/mocks/downloadWorkpad.js | 0 .../tasks/mocks/uiAbsoluteToParsedUrl.ts | 0 .../plugins/canvas/tasks/mocks/uiChrome.js | 0 .../plugins/canvas/tasks/mocks/uiMetric.js | 0 .../plugins/canvas/tasks/mocks/uiNotify.js | 0 .../canvas/tasks/mocks/uiNotifyFormatMsg.js | 0 .../plugins/canvas/types/arguments.ts | 0 .../plugins/canvas/types/assets.ts | 0 .../plugins/canvas/types/canvas.ts | 0 .../plugins/canvas/types/elements.ts | 0 .../plugins/canvas/types/functions.ts | 0 .../plugins/canvas/types/global.d.ts | 0 x-pack/plugins/canvas/types/index.ts | 11 ++- .../canvas/types/react_moment_prototypes.d.ts | 0 .../plugins/canvas/types/renderers.ts | 0 .../plugins/canvas/types/shortcuts.ts | 0 .../plugins/canvas/types/state.ts | 0 .../plugins/canvas/types/style.ts | 0 .../plugins/canvas/types/telemetry.ts | 0 .../plugins/canvas/types/transforms.ts | 0 .../scripts/optimize_tsconfig/tsconfig.json | 2 +- x-pack/tasks/build.ts | 4 +- 1263 files changed, 217 insertions(+), 533 deletions(-) delete mode 100644 x-pack/legacy/plugins/canvas/i18n/index.ts delete mode 100644 x-pack/legacy/plugins/canvas/index.js delete mode 100644 x-pack/legacy/plugins/canvas/public/index.ts delete mode 100644 x-pack/legacy/plugins/canvas/public/legacy.ts delete mode 100644 x-pack/legacy/plugins/canvas/public/legacy_plugin_support.ts delete mode 100644 x-pack/legacy/plugins/canvas/public/legacy_register_interpreter.ts delete mode 100644 x-pack/legacy/plugins/canvas/public/legacy_start.ts delete mode 100644 x-pack/legacy/plugins/canvas/public/lib/function_definitions.js delete mode 100644 x-pack/legacy/plugins/canvas/types/index.ts rename x-pack/{legacy => }/plugins/canvas/.gitignore (100%) rename x-pack/{legacy => }/plugins/canvas/.prettierrc (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/.babelrc (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/addons.js (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/config.js (93%) rename x-pack/{legacy => }/plugins/canvas/.storybook/constants.js (89%) rename x-pack/{legacy => }/plugins/canvas/.storybook/dll_contexts.js (84%) rename x-pack/{legacy => }/plugins/canvas/.storybook/middleware.js (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/preview-head.html (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/storyshots.test.js (96%) rename x-pack/{legacy => }/plugins/canvas/.storybook/webpack.config.js (100%) rename x-pack/{legacy => }/plugins/canvas/.storybook/webpack.dll.config.js (100%) rename x-pack/{legacy => }/plugins/canvas/README.md (100%) rename x-pack/{legacy => }/plugins/canvas/__tests__/fixtures/elasticsearch.js (100%) rename x-pack/{legacy => }/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js (100%) rename x-pack/{legacy => }/plugins/canvas/__tests__/fixtures/function_specs.ts (83%) rename x-pack/{legacy => }/plugins/canvas/__tests__/fixtures/kibana.js (95%) rename x-pack/{legacy => }/plugins/canvas/__tests__/fixtures/workpads.ts (100%) rename x-pack/{legacy => }/plugins/canvas/__tests__/helpers/function_wrapper.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/debug/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/image/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/metric/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/pie/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/plot/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/shape/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/table/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts (84%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts (58%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/expression_types/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/browser/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/browser/location.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/browser/markdown.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/browser/urlparam.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts (87%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/all.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/all.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/any.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/any.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/as.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/as.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/case.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/case.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/clear.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/columns.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/compare.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/containerStyle.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/context.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/context.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/csv.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/date.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/date.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/do.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/do.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/eq.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/exactly.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/formatdate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/getCell.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/get_flot_axis_config.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/get_font_spec.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/get_tick_hash.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/gt.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/gte.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/head.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/head.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/if.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/if.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/image.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/join_rows.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/lt.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/lte.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/map_center.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/math.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/math.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/metric.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/neq.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/palette.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/palette.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/pie.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/pie.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts (98%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot/get_font_spec.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot/get_tick_hash.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/plot/series_style_to_flot.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/ply.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/progress.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/render.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/render.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/repeatImage.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/replace.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/revealImage.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/rounddate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/rowCount.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_map.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts (97%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_search.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/seriesStyle.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/series_style_to_flot.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/shape.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/sort.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/string.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/string.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/switch.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/table.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/table.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/tail.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/time_range.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/timefilter.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/timefilterControl.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata/ci.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata/demo_rows_types.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata/get_demo_rows.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/demodata/shirts.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/escount.ts (94%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts (96%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/essql.ts (94%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/get_field_names.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/is_column_reference.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/pointseries/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_expression_type.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_field_names.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/is_column_reference.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/elastic_logo.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/elastic_outline.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/API.md (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.colorhelpers.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.canvas.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.categories.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.crosshair.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.errorbars.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.fillbetween.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.image.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.navigate.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.resize.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.selection.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.stack.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.symbol.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.threshold.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.time.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/plugin.ts (90%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/__snapshots__/advanced_filter.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/advanced_filter.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/debug.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/__snapshots__/dropdown_filter.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/dropdown_filter.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx (94%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts (96%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts (92%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/error/error.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/error/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/image.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js (92%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/__snapshots__/metric.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/metric.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/metric/component/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/metric/component/metric.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/metric/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/pie/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/pie/plugins/pie.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/plot/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/plot/plot.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/size.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/text.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/gauge.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_bar.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_pill.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/semicircle.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/unicorn.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_bar.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_pill.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/wheel.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/repeat_image.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/reveal_image/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/reveal_image/reveal_image.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow_multi.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/bookmark.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/circle.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/cross.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/hexagon.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/kite.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/pentagon.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/rhombus.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/semicircle.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/speech_bubble.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/square.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/star.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/tag.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle_right.svg (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/table.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/text.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/time_filter.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/renderers/time_filter/time_filter.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/pitch_presentation.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/status_report.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/summary_report.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/theme_dark.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/templates/theme_light.json (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/extended_template.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/simple_template.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/extended_template.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/simple_template.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/extended_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/simple_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/simple_math_function.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/__snapshots__/date_format.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/date_format.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/date_format.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/filter_group.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/file.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/link.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/image_upload.scss (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/number.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/__snapshots__/number_format.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/number_format.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/number_format.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/percentage.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/range.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/select.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/string.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/textarea.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/datasources/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/models/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/models/math.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/models/point_series.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/tags/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/tags/presentation.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/tags/report.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/transforms/formatdate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/transforms/formatnumber.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/transforms/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/transforms/rounddate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/transforms/sort.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/dropdownControl.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/getCell.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/image.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/markdown.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/metric.ts (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/pie.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/plot.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/progress.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/render.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/repeatImage.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/revealImage.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/shape.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/table.js (100%) rename x-pack/{legacy => }/plugins/canvas/canvas_plugin_src/uis/views/timefilterControl.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/autocomplete.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/autocomplete.ts (99%) rename x-pack/{legacy => }/plugins/canvas/common/lib/constants.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/datatable/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/datatable/query.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/dataurl.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/dataurl.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/errors.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/errors.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/expression_form_handlers.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/expression_form_handlers.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/fetch.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/fetch.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/fonts.ts (77%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_colors_from_palette.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_colors_from_palette.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_field_type.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_field_type.ts (100%) rename x-pack/{legacy/plugins/canvas/public => plugins/canvas/common}/lib/get_id.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_legend_config.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/get_legend_config.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/handlebars.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/handlebars.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/hex_to_rgb.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/hex_to_rgb.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/httpurl.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/httpurl.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/missing_asset.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/palettes.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/pivot_object_array.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/pivot_object_array.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/resolve_dataurl.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/resolve_dataurl.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/time_units.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/unquote_string.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/unquote_string.ts (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/url.js (100%) rename x-pack/{legacy => }/plugins/canvas/common/lib/url.test.js (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/README.md (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/capabilities.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/components.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/constants.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/elements/apply_strings.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/elements/element_strings.test.ts (95%) rename x-pack/{legacy => }/plugins/canvas/i18n/elements/element_strings.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/elements/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/errors.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/expression_types.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/all.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/alter_column.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/any.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/as.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/asset.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/axis_config.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/case.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/clear.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/columns.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/compare.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/container_style.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/context.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/csv.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/date.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/demodata.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/do.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/dropdown_control.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/eq.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/escount.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/esdocs.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/essql.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/exactly.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/filterrows.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/filters.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/formatdate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/formatnumber.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/get_cell.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/gt.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/gte.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/head.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/if.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/image.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/join_rows.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/location.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/lt.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/lte.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/map_center.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/map_column.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/markdown.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/math.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/metric.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/neq.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/palette.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/pie.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/plot.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/ply.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/pointseries.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/progress.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/render.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/repeat_image.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/replace.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/reveal_image.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/rounddate.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/row_count.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/saved_lens.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/saved_map.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/saved_search.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/saved_visualization.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/series_style.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/shape.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/sort.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/static_column.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/string.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/switch.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/table.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/tail.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/time_range.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/timefilter.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/timefilter_control.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/timelion.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/to.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/dict/urlparam.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/function_errors.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/function_help.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/functions/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/renderers.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/shortcuts.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/tags.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/templates/apply_strings.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/templates/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/templates/template_strings.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/templates/template_strings.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/transitions.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/ui.ts (100%) rename x-pack/{legacy => }/plugins/canvas/i18n/units.ts (100%) rename x-pack/{legacy => }/plugins/canvas/images/canvas.png (100%) rename x-pack/{legacy => }/plugins/canvas/images/canvas.svg (100%) rename x-pack/{legacy => }/plugins/canvas/images/canvas_blank.svg (100%) rename x-pack/{legacy => }/plugins/canvas/images/icon_black.svg (100%) rename x-pack/{legacy => }/plugins/canvas/images/logo.gif (100%) rename x-pack/{legacy => }/plugins/canvas/public/__tests__/setup.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/application.tsx (94%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/export_app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/export_app.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/export/load_workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/export/routes.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/home/home_app/home_app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/home/home_app/home_app.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/home/home_app/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/home/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/home/routes.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/routes.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/alignment_guide/alignment_guide.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/alignment_guide/alignment_guide.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/alignment_guide/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/app/app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/app/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/app/track_route_change.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add/arg_add.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add/arg_add.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add_popover/arg_add_popover.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add_popover/arg_add_popover.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_add_popover/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/advanced_failure.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/arg_form.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/arg_form.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/arg_label.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/arg_simple_form.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/arg_template_form.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/pending_arg_value.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/arg_form/simple_failure.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/__examples__/asset.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/asset.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/asset_manager.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/asset_manager.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/asset_modal.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_manager/index.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_picker/asset_picker.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_picker/asset_picker.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/asset_picker/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/autocomplete/autocomplete.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/autocomplete/autocomplete.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/autocomplete/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_connection/border_connection.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_connection/border_connection.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_connection/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_resize_handle/border_resize_handle.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_resize_handle/border_resize_handle.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/border_resize_handle/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/clipboard/clipboard.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/clipboard/clipboard.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/clipboard/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_dot/__examples__/color_dot.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_dot/color_dot.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_dot/color_dot.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_dot/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_manager/__examples__/color_manager.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_manager/color_manager.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_manager/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_palette/__examples__/color_palette.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_palette/color_palette.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_palette/color_palette.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_palette/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker/__examples__/color_picker.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker/color_picker.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker_popover/__examples__/__snapshots__/color_picker_popover.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker_popover/__examples__/color_picker_popover.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker_popover/color_picker_popover.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/color_picker_popover/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/confirm_modal/confirm_modal.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/confirm_modal/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/custom_element_modal/__examples__/custom_element_modal.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/custom_element_modal/custom_element_modal.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/custom_element_modal/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource_component.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource_preview/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/datasource_selector.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datasource/no_datasource.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datatable/datatable.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datatable/datatable.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/datatable/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/__examples__/__snapshots__/debug.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/__examples__/helpers.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/debug.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/debug.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/debug/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dom_preview/dom_preview.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dom_preview/dom_preview.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dom_preview/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/download/__tests__/download.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/download/download.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/download/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/dragbox_annotation/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_controls.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/__examples__/element_card.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/element_card.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/element_card.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_card/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_config/element_config.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_config/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_content/element_content.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_content/element_content.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_content/index.js (92%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_content/invalid_element_type.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_content/invalid_expression.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_share_container/element_share_container.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_share_container/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_wrapper/element_wrapper.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_wrapper/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/element_wrapper/lib/handlers.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/embeddable_flyout/flyout.tsx (95%) rename x-pack/{legacy => }/plugins/canvas/public/components/embeddable_flyout/index.tsx (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/enhance/error_boundary.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/enhance/stateful_prop.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/error/error.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/error/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/error/show_debugging.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_field_select/es_field_select.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_field_select/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_fields_select/es_fields_select.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_fields_select/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_index_select/es_index_select.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/es_index_select/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression/element_not_selected.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression/expression.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression/expression.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression/index.js (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression_input/__examples__/__snapshots__/expression_input.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression_input/expression_input.tsx (98%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression_input/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/expression_input/reference.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/file_upload/file_upload.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/file_upload/file_upload.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/font_picker/font_picker.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/font_picker/font_picker.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/font_picker/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/format_select/format_select.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/format_select/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/fullscreen/fullscreen.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/fullscreen/fullscreen.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/fullscreen/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_form.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_form.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_form_component.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_form_context_error.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_form_context_pending.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/function_unknown.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form_list/function_form_list.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/function_form_list/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/help_menu/help_menu.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/help_menu/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/hover_annotation/hover_annotation.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/hover_annotation/hover_annotation.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/hover_annotation/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/item_grid/__examples__/item_grid.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/item_grid/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/item_grid/item_grid.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/keyboard_shortcuts_doc.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/keyboard_shortcuts_doc/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/keyboard_shortcuts_doc/keyboard_shortcuts_doc.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/link/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/link/link.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/loading/__tests__/loading.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/loading/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/loading/loading.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/loading/loading.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/navbar/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/navbar/navbar.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/navbar/navbar.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_config/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_config/page_config.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_manager/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_manager/page_manager.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_manager/page_manager.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_preview/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_preview/page_controls.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/page_preview/page_preview.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/paginate/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/paginate/paginate.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_picker/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_picker/palette_picker.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_picker/palette_picker.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_swatch/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_swatch/palette_swatch.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/palette_swatch/palette_swatch.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/popover/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/popover/popover.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/positionable/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/positionable/positionable.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/positionable/positionable.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/render_to_dom/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/render_to_dom/render_to_dom.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/render_with_fn/index.js (92%) rename x-pack/{legacy => }/plugins/canvas/public/components/render_with_fn/lib/handlers.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/render_with_fn/render_with_fn.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/rotation_handle/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/rotation_handle/rotation_handle.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/rotation_handle/rotation_handle.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/router/canvas_loading.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/router/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/router/router.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/element_grid.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/index.ts (98%) rename x-pack/{legacy => }/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker/__examples__/__snapshots__/shape_picker.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker/__examples__/shape_picker.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker/shape_picker.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker/shape_picker.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker_popover/__examples__/__snapshots__/shape_picker_popover.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker_popover/__examples__/shape_picker_popover.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker_popover/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_preview/__examples__/__snapshots__/shape_preview.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_preview/__examples__/shape_preview.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_preview/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_preview/shape_preview.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/shape_preview/shape_preview.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/group_settings.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/multi_element_settings.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/__examples__/group_settings.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/__examples__/multi_element_settings.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/element_settings/element_settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/element_settings/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/global_config.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/group_settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/multi_element_settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/sidebar.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/sidebar.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/sidebar_content.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/sidebar_section.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar/sidebar_section_title.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar_header/__examples__/sidebar_header.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar_header/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar_header/sidebar_header.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/sidebar_header/sidebar_header.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag/__examples__/tag.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag/tag.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag_list/__examples__/__snapshots__/tag_list.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag_list/__examples__/tag_list.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag_list/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tag_list/tag_list.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/text_style_picker/font_sizes.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/text_style_picker/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/text_style_picker/text_style_picker.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tool_tip_shortcut/__examples__/__snapshots__/tool_tip_shortcut.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tool_tip_shortcut/__examples__/tool_tip_shortcut.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tool_tip_shortcut/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tool_tip_shortcut/tool_tip_shortcut.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/__examples__/toolbar.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/toolbar.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/toolbar.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/tray/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/tray/tray.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/toolbar/tray/tray.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tooltip_annotation/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tooltip_icon/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/tooltip_icon/tooltip_icon.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad/workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad/workpad.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_color_picker/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_config/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_config/workpad_config.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/__snapshots__/edit_menu.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/edit_menu/edit_menu.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/edit_menu/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/element_menu/__examples__/__snapshots__/element_menu.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/element_menu/__examples__/element_menu.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/element_menu/element_menu.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/element_menu/index.tsx (95%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/fullscreen_control/fullscreen_control.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/fullscreen_control/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/refresh_control/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/refresh_control/refresh_control.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/pdf_panel.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/share_menu.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/__examples__/pdf_panel.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/__examples__/share_menu.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/runtime_step.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/share_website_flyout.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/snippets_step.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/flyout/workpad_step.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/index.ts (94%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/pdf_panel.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/share_menu.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/share_menu.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/share_menu/utils.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/__examples__/__snapshots__/view_menu.stories.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/__examples__/view_menu.stories.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/auto_refresh_controls.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/custom_interval.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/index.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/kiosk_controls.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/lib/get_fit_zoom_scale.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/view_menu.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/view_menu/view_menu.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_header/workpad_header.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/index.js (98%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/upload_workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_create.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_dropzone/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_loader.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_loader.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_loader/workpad_search.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_manager/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_manager/workpad_manager.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/integration_utils.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/positioning_utils.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/prop_types.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/utils.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_interactive_page/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interaction_boundary.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_interactive_page/workpad_interactive_page.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_page.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_static_page/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_static_page/static_workpad_page.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_page/workpad_static_page/workpad_static_page.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_shortcuts/index.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_templates/index.js (94%) rename x-pack/{legacy => }/plugins/canvas/public/components/workpad_templates/workpad_templates.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_type.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/color.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/simple_template.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/extended_template.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/simple_template.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/appearance_form.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/border_form.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/extended_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/font.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/extended_template.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/extended_template.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/simple_template.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/extended_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/base_form.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/datasource.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/function_form.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/model.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/transform.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/expression_types/view.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/feature_catalogue_entry.ts (87%) rename x-pack/{legacy => }/plugins/canvas/public/functions/__tests__/asset.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/functions/asset.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/functions/filters.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/functions/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/functions/timelion.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/functions/to.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/icon.svg (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/find_expression_type.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/get_pretty_shortcut.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/history_provider.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/modify_path.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/readable_color.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/resolved_arg.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/__tests__/time_interval.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/common.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/functional.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/geometry.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/gestures.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/index.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/layout.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/layout_functions.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/matrix.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/matrix2d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/select.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/store.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/aeroelastic/tsconfig.json (87%) rename x-pack/{legacy => }/plugins/canvas/public/lib/app_handler_creators.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/app_state.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/arg_helpers.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/breadcrumbs.ts (92%) rename x-pack/{legacy => }/plugins/canvas/public/lib/build_bool_array.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/build_embeddable_filters.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/build_embeddable_filters.ts (92%) rename x-pack/{legacy => }/plugins/canvas/public/lib/clipboard.test.ts (86%) rename x-pack/{legacy => }/plugins/canvas/public/lib/clipboard.ts (90%) rename x-pack/{legacy => }/plugins/canvas/public/lib/clone_subgraphs.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/custom_element_service.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/doc_title.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/documentation_links.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/dom.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/download_workpad.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/elastic_logo.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/elastic_outline.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/element.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/element_handler_creators.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/elements_registry.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/es_service.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/extract_search.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/filters.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/find_existing_asset.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/find_expression_type.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/flatten_panel_tree.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/fullscreen.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/get_client_platform.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/get_es_filter.js (100%) rename x-pack/{legacy/plugins/canvas/public/legacy_register_feature.ts => plugins/canvas/public/lib/get_id.ts} (53%) rename x-pack/{legacy => }/plugins/canvas/public/lib/get_pretty_shortcut.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/get_tags_filter.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/get_window.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/history_provider.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/is_text_input.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/keymap.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/legend_options.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/load_expression_types.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/load_transitions.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/loading_indicator.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/modify_path.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/modify_url.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/monaco_language_def.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/parse_single_function_chain.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/readable_color.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/resolved_arg.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/router_provider.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/run_interpreter.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/shortcut_manager.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/sync_filter_expression.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/tag.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/tags_registry.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/template.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/template_from_react_component.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/templates_registry.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/time_duration.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/time_interval.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/transitions_registry.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/ui_metric.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/window_error_handler.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/lib/workpad_service.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/plugin.tsx (80%) rename x-pack/{legacy => }/plugins/canvas/public/plugin_api.ts (97%) rename x-pack/{legacy => }/plugins/canvas/public/registries.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/services/index.ts (96%) rename x-pack/{legacy => }/plugins/canvas/public/services/notify.ts (91%) rename x-pack/{legacy => }/plugins/canvas/public/services/platform.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/assets.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/elements.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/embeddable.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/history.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/pages.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/resolved_args.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/transient.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/actions/workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/defaults.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/initial_state.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts (99%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/app_ready.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/breadcrumbs.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/element_stats.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/es_persist.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/fullscreen.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/history.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/in_flight.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/resolved_args.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/workpad_autoplay.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/workpad_refresh.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/middleware/workpad_update.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/__tests__/elements.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/__tests__/fixtures/action_creator.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/__tests__/resolved_args.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/app.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/assets.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/elements.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/embeddable.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/embeddables.test.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/history.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/index.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/pages.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/resolved_args.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/transient.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/reducers/workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/__tests__/resolved_args.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/__tests__/workpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/app.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/assets.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/resolved_args.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/state/selectors/workpad.ts (99%) rename x-pack/{legacy => }/plugins/canvas/public/state/store.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/store.ts (94%) rename x-pack/{legacy => }/plugins/canvas/public/style/hackery.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/style/index.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/style/main.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/fade/fade.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/fade/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/rotate/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/rotate/rotate.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/slide/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/slide/slide.scss (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/transition.js (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/zoom/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/public/transitions/zoom/zoom.scss (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/_helpers.js (78%) rename x-pack/{legacy => }/plugins/canvas/scripts/jest.js (94%) rename x-pack/{legacy => }/plugins/canvas/scripts/kbn.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/lint.js (69%) rename x-pack/{legacy => }/plugins/canvas/scripts/shareable_runtime.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/storybook.js (92%) rename x-pack/{legacy => }/plugins/canvas/scripts/storybook_new.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test_browser.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test_common.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test_dev.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test_plugins.js (100%) rename x-pack/{legacy => }/plugins/canvas/scripts/test_server.js (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/README.md (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/__mocks__/supported_renderers.js (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/api/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/api/shareable.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/canvas.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/page.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/rendered_element.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/canvas.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/page.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__examples__/rendered_element.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/app.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/canvas.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/canvas.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.components.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/page_controls.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/scrubber.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/title.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/footer.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/page_controls.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/scrubber.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__examples__/title.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__tests__/page_controls.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__tests__/page_preview.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__tests__/scrubber.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/__tests__/title.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/footer.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/footer.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/page_controls.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/page_preview.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/page_preview.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/scrubber.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.components.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/toolbar_settings.examples.storyshot (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/autoplay_settings.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/settings.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/toolbar_settings.examples.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/autoplay_settings.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/toolbar_settings.test.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/autoplay_settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/settings/toolbar_settings.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/footer/title.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/page.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/page.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/rendered_element.module.scss (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/components/rendered_element.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/constants.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/constants.js (92%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/constants_static.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/constants_static.js (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/context/actions.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/context/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/context/reducer.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/context/state.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/css_modules.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/index.html (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/index.ts (81%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/postcss.config.js (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/supported_renderers.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/supported_renderers.js (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/template.html (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/context.tsx (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/context_example.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/context_jest.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/index.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/interactions.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/selectors.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/utils.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/workpads/austin.json (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/workpads/hello.json (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/test/workpads/test.json (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/types.ts (100%) rename x-pack/{legacy => }/plugins/canvas/shareable_runtime/webpack.config.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/customElementService.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/downloadWorkpad.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/uiAbsoluteToParsedUrl.ts (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/uiChrome.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/uiMetric.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/uiNotify.js (100%) rename x-pack/{legacy => }/plugins/canvas/tasks/mocks/uiNotifyFormatMsg.js (100%) rename x-pack/{legacy => }/plugins/canvas/types/arguments.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/assets.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/canvas.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/elements.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/functions.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/global.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/react_moment_prototypes.d.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/renderers.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/shortcuts.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/state.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/style.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/telemetry.ts (100%) rename x-pack/{legacy => }/plugins/canvas/types/transforms.ts (100%) diff --git a/.eslintignore b/.eslintignore index 53b3d80720439..362b3e42d48e5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -26,10 +26,10 @@ target /src/plugins/vis_type_timelion/public/webpackShims/jquery.flot.* /x-pack/legacy/plugins/**/__tests__/fixtures/** /x-pack/plugins/apm/e2e/cypress/**/snapshots.js -/x-pack/legacy/plugins/canvas/canvas_plugin -/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts -/x-pack/legacy/plugins/canvas/shareable_runtime/build -/x-pack/legacy/plugins/canvas/storybook +/x-pack/plugins/canvas/canvas_plugin +/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts +/x-pack/plugins/canvas/shareable_runtime/build +/x-pack/plugins/canvas/storybook /x-pack/plugins/monitoring/public/lib/jquery_flot /x-pack/legacy/plugins/infra/common/graphql/types.ts /x-pack/legacy/plugins/infra/public/graphql/types.ts diff --git a/.eslintrc.js b/.eslintrc.js index 52a83452bd00f..dde0ce010d4d4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -89,7 +89,7 @@ module.exports = { }, }, { - files: ['x-pack/legacy/plugins/canvas/**/*.{js,ts,tsx}'], + files: ['x-pack/plugins/canvas/**/*.{js,ts,tsx}'], rules: { 'react-hooks/exhaustive-deps': 'off', 'jsx-a11y/click-events-have-key-events': 'off', @@ -893,7 +893,7 @@ module.exports = { * Canvas overrides */ { - files: ['x-pack/legacy/plugins/canvas/**/*.js'], + files: ['x-pack/plugins/canvas/**/*.js'], rules: { radix: 'error', @@ -937,12 +937,12 @@ module.exports = { }, { files: [ - 'x-pack/legacy/plugins/canvas/gulpfile.js', - 'x-pack/legacy/plugins/canvas/scripts/*.js', - 'x-pack/legacy/plugins/canvas/tasks/*.js', - 'x-pack/legacy/plugins/canvas/tasks/**/*.js', - 'x-pack/legacy/plugins/canvas/__tests__/**/*.js', - 'x-pack/legacy/plugins/canvas/**/{__tests__,__test__,__jest__,__fixtures__,__mocks__}/**/*.js', + 'x-pack/plugins/canvas/gulpfile.js', + 'x-pack/plugins/canvas/scripts/*.js', + 'x-pack/plugins/canvas/tasks/*.js', + 'x-pack/plugins/canvas/tasks/**/*.js', + 'x-pack/plugins/canvas/__tests__/**/*.js', + 'x-pack/plugins/canvas/**/{__tests__,__test__,__jest__,__fixtures__,__mocks__}/**/*.js', ], rules: { 'import/no-extraneous-dependencies': [ @@ -955,7 +955,7 @@ module.exports = { }, }, { - files: ['x-pack/legacy/plugins/canvas/canvas_plugin_src/**/*.js'], + files: ['x-pack/plugins/canvas/canvas_plugin_src/**/*.js'], globals: { canvas: true, $: true }, rules: { 'import/no-unresolved': [ @@ -967,13 +967,13 @@ module.exports = { }, }, { - files: ['x-pack/legacy/plugins/canvas/public/**/*.js'], + files: ['x-pack/plugins/canvas/public/**/*.js'], env: { browser: true, }, }, { - files: ['x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/**/*.js'], + files: ['x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/**/*.js'], env: { jquery: true, }, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 280cb6fbd1b1d..638e86ef375fe 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -77,7 +77,7 @@ /x-pack/legacy/plugins/beats_management/ @elastic/beats # Canvas -/x-pack/legacy/plugins/canvas/ @elastic/kibana-canvas +/x-pack/plugins/canvas/ @elastic/kibana-canvas # Observability UIs /x-pack/legacy/plugins/infra/ @elastic/logs-metrics-ui diff --git a/.sass-lint.yml b/.sass-lint.yml index 44b4d49384136..c8985108dabf2 100644 --- a/.sass-lint.yml +++ b/.sass-lint.yml @@ -5,14 +5,14 @@ files: - 'src/plugins/vis_type_vislib/**/*.s+(a|c)ss' - 'src/plugins/vis_type_xy/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/security/**/*.s+(a|c)ss' - - 'x-pack/legacy/plugins/canvas/**/*.s+(a|c)ss' + - 'x-pack/plugins/canvas/**/*.s+(a|c)ss' - 'x-pack/plugins/triggers_actions_ui/**/*.s+(a|c)ss' - 'x-pack/plugins/lens/**/*.s+(a|c)ss' - 'x-pack/plugins/cross_cluster_replication/**/*.s+(a|c)ss' - 'x-pack/legacy/plugins/maps/**/*.s+(a|c)ss' - 'x-pack/plugins/maps/**/*.s+(a|c)ss' ignore: - - 'x-pack/legacy/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss' + - 'x-pack/plugins/canvas/shareable_runtime/**/*.s+(a|c)ss' rules: quotes: - 2 diff --git a/package.json b/package.json index 30d488eb04992..178ccbac7d420 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "test:ftr:server": "node scripts/functional_tests_server", "test:ftr:runner": "node scripts/functional_test_runner", "test:coverage": "grunt test:coverage", - "typespec": "typings-tester --config x-pack/legacy/plugins/canvas/public/lib/aeroelastic/tsconfig.json x-pack/legacy/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts", + "typespec": "typings-tester --config x-pack/plugins/canvas/public/lib/aeroelastic/tsconfig.json x-pack/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts", "checkLicenses": "node scripts/check_licenses --dev", "build": "node scripts/build --all-platforms", "start": "node scripts/kibana --dev", diff --git a/src/cli/cluster/cluster_manager.ts b/src/cli/cluster/cluster_manager.ts index 97dec3eead303..3b3e4d78320d2 100644 --- a/src/cli/cluster/cluster_manager.ts +++ b/src/cli/cluster/cluster_manager.ts @@ -268,7 +268,7 @@ export class ClusterManager { fromRoot('x-pack/plugins/siem/cypress'), fromRoot('x-pack/plugins/apm/e2e'), fromRoot('x-pack/plugins/apm/scripts'), - fromRoot('x-pack/legacy/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes, + fromRoot('x-pack/plugins/canvas/canvas_plugin_src'), // prevents server from restarting twice for Canvas plugin changes, 'plugins/java_languageserver', ]; diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index 8630221b3e94f..601dcc86352a7 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -35,8 +35,8 @@ export const IGNORE_FILE_GLOBS = [ '**/Gruntfile.js', 'tasks/config/**/*', '**/{Dockerfile,docker-compose.yml}', - 'x-pack/legacy/plugins/canvas/tasks/**/*', - 'x-pack/legacy/plugins/canvas/canvas_plugin_src/**/*', + 'x-pack/plugins/canvas/tasks/**/*', + 'x-pack/plugins/canvas/canvas_plugin_src/**/*', 'x-pack/plugins/monitoring/public/lib/jquery_flot/**/*', '**/.*', '**/{webpackShims,__mocks__}/**/*', @@ -48,7 +48,7 @@ export const IGNORE_FILE_GLOBS = [ 'vars/*', // Files in this directory must match a pre-determined name in some cases. - 'x-pack/legacy/plugins/canvas/.storybook/*', + 'x-pack/plugins/canvas/.storybook/*', // filename must match language code which requires capital letters '**/translations/*.json', diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 0e91f0a214a45..416702c56d852 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -20,7 +20,7 @@ export const storybookAliases = { advanced_ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js', apm: 'x-pack/plugins/apm/scripts/storybook.js', - canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js', + canvas: 'x-pack/plugins/canvas/scripts/storybook_new.js', codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts', dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/scripts/storybook.js', drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js', diff --git a/test/scripts/jenkins_xpack.sh b/test/scripts/jenkins_xpack.sh index 951ba8e22d885..c1243527de2c3 100755 --- a/test/scripts/jenkins_xpack.sh +++ b/test/scripts/jenkins_xpack.sh @@ -38,7 +38,7 @@ else cd "$XPACK_DIR" # build runtime for canvas echo "NODE_ENV=$NODE_ENV" - node ./legacy/plugins/canvas/scripts/shareable_runtime + node ./plugins/canvas/scripts/shareable_runtime node --max-old-space-size=6144 scripts/jest --ci --verbose --detectOpenHandles --coverage # rename file in order to be unique one test -f ../target/kibana-coverage/jest/coverage-final.json \ diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index ccf8739dd9730..a033515fef8b0 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -8,7 +8,7 @@ "xpack.alertingBuiltins": "plugins/alerting_builtins", "xpack.apm": ["legacy/plugins/apm", "plugins/apm"], "xpack.beatsManagement": "legacy/plugins/beats_management", - "xpack.canvas": "legacy/plugins/canvas", + "xpack.canvas": "plugins/canvas", "xpack.dashboard": "plugins/dashboard_enhanced", "xpack.crossClusterReplication": "plugins/cross_cluster_replication", "xpack.dashboardMode": "legacy/plugins/dashboard_mode", diff --git a/x-pack/.kibana-plugin-helpers.json b/x-pack/.kibana-plugin-helpers.json index 032783d9309f1..ed0b38841c1a8 100644 --- a/x-pack/.kibana-plugin-helpers.json +++ b/x-pack/.kibana-plugin-helpers.json @@ -29,8 +29,8 @@ "!legacy/plugins/**/__snapshots__", "!legacy/plugins/**/__snapshots__/*", "!legacy/plugins/**/__mocks__/*", - "!legacy/plugins/canvas/shareable_runtime/test", - "!legacy/plugins/canvas/shareable_runtime/test/**/*" + "!plugins/canvas/shareable_runtime/test", + "!plugins/canvas/shareable_runtime/test/**/*" ], "skipInstallDependencies": true } diff --git a/x-pack/legacy/plugins/canvas/i18n/index.ts b/x-pack/legacy/plugins/canvas/i18n/index.ts deleted file mode 100644 index 864311d34aca0..0000000000000 --- a/x-pack/legacy/plugins/canvas/i18n/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from './capabilities'; -export * from './components'; -export * from './constants'; -export * from './errors'; -export * from './expression_types'; -export * from './elements'; -export * from './functions'; -export * from './renderers'; -export * from './shortcuts'; -export * from './tags'; -export * from './transitions'; -export * from './ui'; -export * from './units'; diff --git a/x-pack/legacy/plugins/canvas/index.js b/x-pack/legacy/plugins/canvas/index.js deleted file mode 100644 index d9ea54de2d8a8..0000000000000 --- a/x-pack/legacy/plugins/canvas/index.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { resolve } from 'path'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/server'; -import { CANVAS_APP, CANVAS_TYPE, CUSTOM_ELEMENT_TYPE } from './common/lib'; - -export function canvas(kibana) { - return new kibana.Plugin({ - id: CANVAS_APP, - configPrefix: 'xpack.canvas', - require: ['kibana', 'elasticsearch', 'xpack_main'], - publicDir: resolve(__dirname, 'public'), - uiExports: { - app: { - title: 'Canvas', - description: 'Data driven workpads', - icon: 'plugins/canvas/icon.svg', - euiIconType: 'canvasApp', - main: 'plugins/canvas/legacy_start', - category: DEFAULT_APP_CATEGORIES.analyze, - }, - interpreter: ['plugins/canvas/legacy_register_interpreter'], - styleSheetPaths: resolve(__dirname, 'public/style/index.scss'), - hacks: [ - // window.onerror override - 'plugins/canvas/lib/window_error_handler.js', - ], - home: ['plugins/canvas/legacy_register_feature'], - savedObjectsManagement: { - [CANVAS_TYPE]: { - icon: 'canvasApp', - defaultSearchField: 'name', - isImportableAndExportable: true, - getTitle(obj) { - return obj.attributes.name; - }, - getInAppUrl(obj) { - return { - path: `/app/canvas#/workpad/${encodeURIComponent(obj.id)}`, - uiCapabilitiesPath: 'canvas.show', - }; - }, - }, - [CUSTOM_ELEMENT_TYPE]: { - icon: 'canvasApp', - defaultSearchField: 'name', - isImportableAndExportable: true, - getTitle(obj) { - return obj.attributes.displayName; - }, - }, - }, - }, - - config: Joi => { - return Joi.object({ - enabled: Joi.boolean().default(true), - indexPrefix: Joi.string().default('.canvas'), - }).default(); - }, - - init: () => undefined, - }); -} diff --git a/x-pack/legacy/plugins/canvas/public/index.ts b/x-pack/legacy/plugins/canvas/public/index.ts deleted file mode 100644 index b053920fec6e4..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { - PluginInitializer, - PluginInitializerContext, - CoreStart, -} from '../../../../../src/core/public'; -import { CanvasSetup, CanvasStart, CanvasSetupDeps, CanvasStartDeps, CanvasPlugin } from './plugin'; -import { CanvasServices } from './services'; - -export const plugin: PluginInitializer< - CanvasSetup, - CanvasStart, - CanvasSetupDeps, - CanvasStartDeps -> = (initializerContext: PluginInitializerContext) => { - return new CanvasPlugin(); -}; - -export interface WithKibanaProps { - kibana: { - services: CoreStart & CanvasStartDeps & { canvas: CanvasServices }; - }; -} - -// These are your public types & static code -export { CanvasSetup, CanvasStart }; diff --git a/x-pack/legacy/plugins/canvas/public/legacy.ts b/x-pack/legacy/plugins/canvas/public/legacy.ts deleted file mode 100644 index f4a2b309b3499..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/legacy.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { npSetup, npStart } from 'ui/new_platform'; -import { CanvasStartDeps, CanvasSetupDeps } from './plugin'; // eslint-disable-line import/order - -// @ts-ignore Untyped Kibana Lib -import chrome, { loadingCount } from 'ui/chrome'; // eslint-disable-line import/order -// @ts-ignore Untyped Kibana Lib -import { formatMsg } from '../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order - -const shimCoreSetup = { - ...npSetup.core, -}; -const shimCoreStart = { - ...npStart.core, -}; - -const shimSetupPlugins: CanvasSetupDeps = { - data: npSetup.plugins.data, - expressions: npSetup.plugins.expressions, - home: npSetup.plugins.home, - usageCollection: npSetup.plugins.usageCollection, -}; -const shimStartPlugins: CanvasStartDeps = { - ...npStart.plugins, - embeddable: npStart.plugins.embeddable, - expressions: npStart.plugins.expressions, - inspector: npStart.plugins.inspector, - uiActions: npStart.plugins.uiActions, -}; - -// These methods are intended to be a replacement for import from 'ui/whatever' -// These will go away once all of this one plugin start/setup properly -// injects wherever these need to go. -export function getCoreSetup() { - return shimCoreSetup; -} - -export function getCoreStart() { - return shimCoreStart; -} - -export function getSetupPlugins() { - return shimSetupPlugins; -} - -export function getStartPlugins() { - return shimStartPlugins; -} diff --git a/x-pack/legacy/plugins/canvas/public/legacy_plugin_support.ts b/x-pack/legacy/plugins/canvas/public/legacy_plugin_support.ts deleted file mode 100644 index cfc3de8f6d54c..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/legacy_plugin_support.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// @ts-ignore -import { Registry, registryFactory } from '@kbn/interpreter/common'; - -type specFn = (...args: any[]) => { name: string }; - -const fnWrapper = (fn: specFn) => { - const obj = fn(); - return () => ({ - name: obj.name, - fn, - }); -}; - -class LegacyRegistry extends Registry { - register(fn: specFn) { - super.register(fnWrapper(fn)); - } - - getOriginalFns() { - return this.toArray().map(entry => entry.fn); - } -} - -export const legacyRegistries = { - browserFunctions: new LegacyRegistry(), - renderers: new LegacyRegistry(), - types: new LegacyRegistry(), - elements: new LegacyRegistry(), - transformUIs: new LegacyRegistry(), - datasourceUIs: new LegacyRegistry(), - modelUIs: new LegacyRegistry(), - viewUIs: new LegacyRegistry(), - argumentUIs: new LegacyRegistry(), - templates: new LegacyRegistry(), - tagUIs: new LegacyRegistry(), -}; - -(global as any).kbnInterpreter = Object.assign( - (global as any).kbnInterpreter || {}, - registryFactory(legacyRegistries) -); diff --git a/x-pack/legacy/plugins/canvas/public/legacy_register_interpreter.ts b/x-pack/legacy/plugins/canvas/public/legacy_register_interpreter.ts deleted file mode 100644 index 274a9875d123d..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/legacy_register_interpreter.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { npSetup } from 'ui/new_platform'; -import { functions } from '../canvas_plugin_src/functions/browser'; -import { typeFunctions } from '../canvas_plugin_src/expression_types'; -// @ts-ignore untyped local -import { renderFunctions } from '../canvas_plugin_src/renderers'; - -functions.forEach(npSetup.plugins.expressions.registerFunction); -typeFunctions.forEach(npSetup.plugins.expressions.registerType); -renderFunctions.forEach(npSetup.plugins.expressions.registerRenderer); - -// eslint-disable-next-line import/no-default-export -export default functions; diff --git a/x-pack/legacy/plugins/canvas/public/legacy_start.ts b/x-pack/legacy/plugins/canvas/public/legacy_start.ts deleted file mode 100644 index ac647fe8a5a93..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/legacy_start.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// TODO: These are legacy imports. We should work to have all of these come from New Platform -// Import the uiExports that the application uses -// These will go away as these plugins are converted to NP -import 'ui/autoload/all'; -import 'uiExports/savedObjectTypes'; -import 'uiExports/spyModes'; -import 'uiExports/embeddableFactories'; -import 'uiExports/interpreter'; - -import './legacy_plugin_support'; -// load application code -import 'uiExports/canvas'; - -import { PluginInitializerContext } from '../../../../../src/core/public'; -import { plugin } from './'; -import { getCoreStart, getStartPlugins, getSetupPlugins, getCoreSetup } from './legacy'; -const pluginInstance = plugin({} as PluginInitializerContext); - -// Setup and Startup the plugin -export const setup = pluginInstance.setup(getCoreSetup(), getSetupPlugins()); -export const start = pluginInstance.start(getCoreStart(), getStartPlugins()); diff --git a/x-pack/legacy/plugins/canvas/public/lib/function_definitions.js b/x-pack/legacy/plugins/canvas/public/lib/function_definitions.js deleted file mode 100644 index 36ad0ba0b0015..0000000000000 --- a/x-pack/legacy/plugins/canvas/public/lib/function_definitions.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import uniqBy from 'lodash.uniqby'; -import { npStart } from 'ui/new_platform'; -import { getServerFunctions } from '../state/selectors/app'; - -export async function getFunctionDefinitions(state) { - const serverFunctions = getServerFunctions(state); - return uniqBy( - serverFunctions.concat(Object.values(npStart.plugins.expressions.getFunctions())), - 'name' - ); -} diff --git a/x-pack/legacy/plugins/canvas/types/index.ts b/x-pack/legacy/plugins/canvas/types/index.ts deleted file mode 100644 index 21b3d2643c44c..0000000000000 --- a/x-pack/legacy/plugins/canvas/types/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -export * from '../../../../../src/plugins/expressions/common'; -export * from './assets'; -export * from './canvas'; -export * from './elements'; -export * from './functions'; -export * from './renderers'; -export * from './shortcuts'; -export * from './state'; -export * from './style'; -export * from './telemetry'; diff --git a/x-pack/package.json b/x-pack/package.json index 5461b21b571f8..8d3d13d8cd75d 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -6,7 +6,7 @@ "license": "Elastic-License", "scripts": { "kbn": "node ../scripts/kbn", - "kbn:bootstrap": "node legacy/plugins/canvas/scripts/storybook --clean", + "kbn:bootstrap": "node plugins/canvas/scripts/storybook --clean", "start": "gulp dev", "build": "gulp build", "testonly": "echo 'Deprecated, use `yarn test`' && gulp test", diff --git a/x-pack/legacy/plugins/canvas/.gitignore b/x-pack/plugins/canvas/.gitignore similarity index 100% rename from x-pack/legacy/plugins/canvas/.gitignore rename to x-pack/plugins/canvas/.gitignore diff --git a/x-pack/legacy/plugins/canvas/.prettierrc b/x-pack/plugins/canvas/.prettierrc similarity index 100% rename from x-pack/legacy/plugins/canvas/.prettierrc rename to x-pack/plugins/canvas/.prettierrc diff --git a/x-pack/legacy/plugins/canvas/.storybook/.babelrc b/x-pack/plugins/canvas/.storybook/.babelrc similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/.babelrc rename to x-pack/plugins/canvas/.storybook/.babelrc diff --git a/x-pack/legacy/plugins/canvas/.storybook/addons.js b/x-pack/plugins/canvas/.storybook/addons.js similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/addons.js rename to x-pack/plugins/canvas/.storybook/addons.js diff --git a/x-pack/legacy/plugins/canvas/.storybook/config.js b/x-pack/plugins/canvas/.storybook/config.js similarity index 93% rename from x-pack/legacy/plugins/canvas/.storybook/config.js rename to x-pack/plugins/canvas/.storybook/config.js index 725a3b12666d1..c808a672711ab 100644 --- a/x-pack/legacy/plugins/canvas/.storybook/config.js +++ b/x-pack/plugins/canvas/.storybook/config.js @@ -10,7 +10,7 @@ import { withKnobs } from '@storybook/addon-knobs/react'; import { withInfo } from '@storybook/addon-info'; import { create } from '@storybook/theming'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; // If we're running Storyshots, be sure to register the require context hook. // Otherwise, add the other decorators. @@ -50,7 +50,7 @@ function loadStories() { // Only gather and require CSS files related to Canvas. The other CSS files // are built into the DLL. const css = require.context( - '../../../../../built_assets/css', + '../../../../built_assets/css', true, /plugins\/(?=canvas).*light\.css/ ); @@ -67,7 +67,7 @@ addParameters({ theme: create({ base: 'light', brandTitle: 'Canvas Storybook', - brandUrl: 'https://github.com/elastic/kibana/tree/master/x-pack/legacy/plugins/canvas', + brandUrl: 'https://github.com/elastic/kibana/tree/master/x-pack/plugins/canvas', }), showPanel: true, isFullscreen: false, diff --git a/x-pack/legacy/plugins/canvas/.storybook/constants.js b/x-pack/plugins/canvas/.storybook/constants.js similarity index 89% rename from x-pack/legacy/plugins/canvas/.storybook/constants.js rename to x-pack/plugins/canvas/.storybook/constants.js index 9b59afbaf69f2..258bf208ed877 100644 --- a/x-pack/legacy/plugins/canvas/.storybook/constants.js +++ b/x-pack/plugins/canvas/.storybook/constants.js @@ -7,7 +7,7 @@ const path = require('path'); const DLL_NAME = 'canvas_storybook_dll'; -const KIBANA_ROOT = path.resolve(__dirname, '../../../../..'); +const KIBANA_ROOT = path.resolve(__dirname, '../../../..'); const BUILT_ASSETS = path.resolve(KIBANA_ROOT, 'built_assets'); const DLL_OUTPUT = path.resolve(BUILT_ASSETS, DLL_NAME); diff --git a/x-pack/legacy/plugins/canvas/.storybook/dll_contexts.js b/x-pack/plugins/canvas/.storybook/dll_contexts.js similarity index 84% rename from x-pack/legacy/plugins/canvas/.storybook/dll_contexts.js rename to x-pack/plugins/canvas/.storybook/dll_contexts.js index 273323d065ecf..529fd8aa5c791 100644 --- a/x-pack/legacy/plugins/canvas/.storybook/dll_contexts.js +++ b/x-pack/plugins/canvas/.storybook/dll_contexts.js @@ -11,7 +11,7 @@ // Pull in the built CSS produced by the Kibana server, but not // the Canvas CSS-- we want that in the HMR service. const css = require.context( - '../../../../../built_assets/css', + '../../../../built_assets/css', true, /\.\/plugins\/(?!canvas).*light\.css/ ); @@ -21,15 +21,11 @@ css.keys().forEach(filename => { // Include Legacy styles const uiStyles = require.context( - '../../../../../src/legacy/ui/public/styles', + '../../../../src/legacy/ui/public/styles', false, /[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/ ); uiStyles.keys().forEach(key => uiStyles(key)); -const json = require.context( - '../shareable_runtime/test/workpads', - false, - /\.json$/ -); +const json = require.context('../shareable_runtime/test/workpads', false, /\.json$/); json.keys().forEach(key => json(key)); diff --git a/x-pack/legacy/plugins/canvas/.storybook/middleware.js b/x-pack/plugins/canvas/.storybook/middleware.js similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/middleware.js rename to x-pack/plugins/canvas/.storybook/middleware.js diff --git a/x-pack/legacy/plugins/canvas/.storybook/preview-head.html b/x-pack/plugins/canvas/.storybook/preview-head.html similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/preview-head.html rename to x-pack/plugins/canvas/.storybook/preview-head.html diff --git a/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js b/x-pack/plugins/canvas/.storybook/storyshots.test.js similarity index 96% rename from x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js rename to x-pack/plugins/canvas/.storybook/storyshots.test.js index a679010c67092..59645cad26200 100644 --- a/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js +++ b/x-pack/plugins/canvas/.storybook/storyshots.test.js @@ -7,7 +7,7 @@ import path from 'path'; import moment from 'moment'; import 'moment-timezone'; -import ReactDOM from "react-dom"; +import ReactDOM from 'react-dom'; import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots'; import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer'; @@ -25,8 +25,8 @@ moment.tz.setDefault('UTC'); const testTime = new Date(Date.UTC(2019, 5, 1)); // June 1 2019 Date.now = jest.fn(() => testTime); -// Mock telemetry service -jest.mock('../public/lib/ui_metric', () => ({ trackCanvasUiMetric: () => { } })); +// Mock telemetry service +jest.mock('../public/lib/ui_metric', () => ({ trackCanvasUiMetric: () => {} })); // Mock EUI generated ids to be consistently predictable for snapshots. jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`); @@ -65,9 +65,8 @@ jest.mock('@elastic/eui/packages/react-datepicker', () => { }; }); - // Mock React Portal for components that use modals, tooltips, etc -ReactDOM.createPortal = jest.fn((element) => { +ReactDOM.createPortal = jest.fn(element => { return element; }); diff --git a/x-pack/legacy/plugins/canvas/.storybook/webpack.config.js b/x-pack/plugins/canvas/.storybook/webpack.config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/webpack.config.js rename to x-pack/plugins/canvas/.storybook/webpack.config.js diff --git a/x-pack/legacy/plugins/canvas/.storybook/webpack.dll.config.js b/x-pack/plugins/canvas/.storybook/webpack.dll.config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/.storybook/webpack.dll.config.js rename to x-pack/plugins/canvas/.storybook/webpack.dll.config.js diff --git a/x-pack/legacy/plugins/canvas/README.md b/x-pack/plugins/canvas/README.md similarity index 100% rename from x-pack/legacy/plugins/canvas/README.md rename to x-pack/plugins/canvas/README.md diff --git a/x-pack/legacy/plugins/canvas/__tests__/fixtures/elasticsearch.js b/x-pack/plugins/canvas/__tests__/fixtures/elasticsearch.js similarity index 100% rename from x-pack/legacy/plugins/canvas/__tests__/fixtures/elasticsearch.js rename to x-pack/plugins/canvas/__tests__/fixtures/elasticsearch.js diff --git a/x-pack/legacy/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js b/x-pack/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js similarity index 100% rename from x-pack/legacy/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js rename to x-pack/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js diff --git a/x-pack/legacy/plugins/canvas/__tests__/fixtures/function_specs.ts b/x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts similarity index 83% rename from x-pack/legacy/plugins/canvas/__tests__/fixtures/function_specs.ts rename to x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts index 3ed08268222d0..edf11f5a25c08 100644 --- a/x-pack/legacy/plugins/canvas/__tests__/fixtures/function_specs.ts +++ b/x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts @@ -5,6 +5,6 @@ */ import { functions as browserFns } from '../../canvas_plugin_src/functions/browser'; -import { ExpressionFunction } from '../../../../../../src/plugins/expressions'; +import { ExpressionFunction } from '../../../../../src/plugins/expressions'; export const functionSpecs = browserFns.map(fn => new ExpressionFunction(fn())); diff --git a/x-pack/legacy/plugins/canvas/__tests__/fixtures/kibana.js b/x-pack/plugins/canvas/__tests__/fixtures/kibana.js similarity index 95% rename from x-pack/legacy/plugins/canvas/__tests__/fixtures/kibana.js rename to x-pack/plugins/canvas/__tests__/fixtures/kibana.js index 8caab5c41563c..4503adcec0c2c 100644 --- a/x-pack/legacy/plugins/canvas/__tests__/fixtures/kibana.js +++ b/x-pack/plugins/canvas/__tests__/fixtures/kibana.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { get, has, noop } from 'lodash'; +import { get, has } from 'lodash'; import mockElasticsearch from './elasticsearch_plugin'; const config = { diff --git a/x-pack/legacy/plugins/canvas/__tests__/fixtures/workpads.ts b/x-pack/plugins/canvas/__tests__/fixtures/workpads.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/__tests__/fixtures/workpads.ts rename to x-pack/plugins/canvas/__tests__/fixtures/workpads.ts diff --git a/x-pack/legacy/plugins/canvas/__tests__/helpers/function_wrapper.js b/x-pack/plugins/canvas/__tests__/helpers/function_wrapper.js similarity index 100% rename from x-pack/legacy/plugins/canvas/__tests__/helpers/function_wrapper.js rename to x-pack/plugins/canvas/__tests__/helpers/function_wrapper.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/debug/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/debug/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/image/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/image/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/metric/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/pie/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/pie/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/plot/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/plot/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/shape/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/shape/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/table/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/table/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts b/x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts similarity index 84% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts rename to x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts index fbe7825c3b2c8..74de223b9fcb7 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ExpressionTypeDefinition } from '../../../../../../src/plugins/expressions'; -import { EmbeddableInput } from '../../../../../../src/plugins/embeddable/public'; +import { ExpressionTypeDefinition } from '../../../../../src/plugins/expressions'; +import { EmbeddableInput } from '../../../../../src/plugins/embeddable/public'; import { EmbeddableTypes } from './embeddable_types'; export const EmbeddableExpressionType = 'embeddable'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts b/x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts similarity index 58% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts rename to x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts index 592da1ff039a1..85629936d9ad3 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/expression_types/embeddable_types.ts @@ -3,11 +3,10 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -import { MAP_SAVED_OBJECT_TYPE } from '../../../../../plugins/maps/public'; -import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/plugins/visualizations/public'; -import { LENS_EMBEDDABLE_TYPE } from '../../../../../plugins/lens/common/constants'; -import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/plugins/discover/public'; +import { MAP_SAVED_OBJECT_TYPE } from '../../../../plugins/maps/public'; +import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../src/plugins/visualizations/public'; +import { LENS_EMBEDDABLE_TYPE } from '../../../../plugins/lens/common/constants'; +import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../src/plugins/discover/public'; export const EmbeddableTypes: { lens: string; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/expression_types/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/expression_types/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/expression_types/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/browser/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/location.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/location.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/browser/location.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/markdown.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/markdown.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/urlparam.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/urlparam.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/browser/urlparam.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/browser/urlparam.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts similarity index 87% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts index 1f13157a360f3..b5e5836dc5331 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts @@ -39,63 +39,63 @@ const testTable: Datatable = { rows: [ { name: 'product1', - time: 1517842800950, //05 Feb 2018 15:00:00 GMT + time: 1517842800950, // 05 Feb 2018 15:00:00 GMT price: 605, quantity: 100, in_stock: true, }, { name: 'product1', - time: 1517929200950, //06 Feb 2018 15:00:00 GMT + time: 1517929200950, // 06 Feb 2018 15:00:00 GMT price: 583, quantity: 200, in_stock: true, }, { name: 'product1', - time: 1518015600950, //07 Feb 2018 15:00:00 GMT + time: 1518015600950, // 07 Feb 2018 15:00:00 GMT price: 420, quantity: 300, in_stock: true, }, { name: 'product2', - time: 1517842800950, //05 Feb 2018 15:00:00 GMT + time: 1517842800950, // 05 Feb 2018 15:00:00 GMT price: 216, quantity: 350, in_stock: false, }, { name: 'product2', - time: 1517929200950, //06 Feb 2018 15:00:00 GMT + time: 1517929200950, // 06 Feb 2018 15:00:00 GMT price: 200, quantity: 256, in_stock: false, }, { name: 'product2', - time: 1518015600950, //07 Feb 2018 15:00:00 GMT + time: 1518015600950, // 07 Feb 2018 15:00:00 GMT price: 190, quantity: 231, in_stock: false, }, { name: 'product3', - time: 1517842800950, //05 Feb 2018 15:00:00 GMT + time: 1517842800950, // 05 Feb 2018 15:00:00 GMT price: 67, quantity: 240, in_stock: true, }, { name: 'product4', - time: 1517842800950, //05 Feb 2018 15:00:00 GMT + time: 1517842800950, // 05 Feb 2018 15:00:00 GMT price: 311, quantity: 447, in_stock: false, }, { name: 'product5', - time: 1517842800950, //05 Feb 2018 15:00:00 GMT + time: 1517842800950, // 05 Feb 2018 15:00:00 GMT price: 288, quantity: 384, in_stock: true, diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/all.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/all.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/all.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/all.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/any.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/any.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/any.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/any.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/as.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/as.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/as.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/as.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/axisConfig.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/case.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/case.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/case.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/case.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/clear.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/clear.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/columns.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/columns.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/compare.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/compare.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/containerStyle.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/containerStyle.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/containerStyle.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/containerStyle.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/context.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/context.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/context.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/context.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/csv.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/csv.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/date.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/date.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/date.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/date.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/do.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/do.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/do.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/do.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdownControl.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/eq.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/eq.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/exactly.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/exactly.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatdate.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatdate.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/getCell.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/getCell.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_flot_axis_config.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_flot_axis_config.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_flot_axis_config.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_flot_axis_config.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_font_spec.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_font_spec.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_font_spec.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_font_spec.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_tick_hash.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_tick_hash.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/get_tick_hash.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/get_tick_hash.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gt.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gt.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gte.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/gte.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/head.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/head.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/head.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/head.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/if.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/if.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/if.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/if.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/image.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/image.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/join_rows.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/join_rows.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lt.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lt.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lte.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/lte.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/map_center.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/map_center.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/map_center.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/map_center.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/math.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/math.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/math.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/math.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/metric.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/metric.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/neq.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/neq.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/palette.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/palette.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/palette.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/palette.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/palette.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/palette.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/palette.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/palette.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/pie.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/pie.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/pie.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/pie.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/pie.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/pie.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/pie.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/pie.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts similarity index 98% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts index bdb3c0e8c1b2e..660605c4c54c1 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_flot_axis_config.ts @@ -6,7 +6,7 @@ import { get, map } from 'lodash'; import { Ticks, AxisConfig, isAxisConfig } from '../../../../types'; -import { Style, PointSeriesColumns } from '../../../../../../../../src/plugins/expressions/common'; +import { Style, PointSeriesColumns } from '../../../../../../../src/plugins/expressions/common'; type Position = 'bottom' | 'top' | 'left' | 'right'; interface Config { diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_font_spec.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_font_spec.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_font_spec.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_font_spec.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_tick_hash.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_tick_hash.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/get_tick_hash.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/get_tick_hash.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/series_style_to_flot.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/series_style_to_flot.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/plot/series_style_to_flot.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/plot/series_style_to_flot.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/ply.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/ply.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/progress.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/progress.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/render.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/render.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/render.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/render.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/repeatImage.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeatImage.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/repeatImage.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeatImage.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/replace.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/replace.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/revealImage.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/revealImage.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/revealImage.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rounddate.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rounddate.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rowCount.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/rowCount.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_lens.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_map.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_map.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts index df316d0dd182f..dacdc30e0c6f7 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_map.ts @@ -13,7 +13,7 @@ import { EmbeddableExpression, } from '../../expression_types'; import { getFunctionHelp } from '../../../i18n'; -import { MapEmbeddableInput } from '../../../../../plugins/maps/public'; +import { MapEmbeddableInput } from '../../../../../legacy/plugins/maps/public'; interface Arguments { id: string; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_search.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_search.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_search.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/saved_visualization.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/seriesStyle.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/seriesStyle.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/seriesStyle.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/seriesStyle.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/series_style_to_flot.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style_to_flot.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/series_style_to_flot.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style_to_flot.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/shape.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/shape.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/shape.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/shape.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/sort.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/sort.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/string.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/string.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/string.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/string.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/switch.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/switch.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/table.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/table.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/table.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/table.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/tail.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/tail.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/time_range.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/time_range.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/time_range.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/time_range.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilterControl.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilterControl.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilterControl.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilterControl.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/ci.json b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/ci.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/ci.json rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/ci.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/demo_rows_types.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/demo_rows_types.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/demo_rows_types.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/demo_rows_types.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/get_demo_rows.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/get_demo_rows.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/get_demo_rows.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/get_demo_rows.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/shirts.json b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/shirts.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/demodata/shirts.json rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/demodata/shirts.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/escount.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/escount.ts similarity index 94% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/escount.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/escount.ts index 2ab48fe002979..142331aabf351 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/escount.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/escount.ts @@ -10,7 +10,7 @@ import { } from 'src/plugins/expressions/common'; /* eslint-disable */ // @ts-ignore untyped local -import { buildESRequest } from '../../../../../../plugins/canvas/server/lib/build_es_request'; +import { buildESRequest } from '../../../server/lib/build_es_request'; /* eslint-enable */ import { getFunctionHelp } from '../../../i18n'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts similarity index 96% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts index 180afc89322c3..1eb0a7c74780c 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/esdocs.ts @@ -8,7 +8,7 @@ import squel from 'squel'; import { ExpressionFunctionDefinition } from 'src/plugins/expressions'; /* eslint-disable */ // @ts-ignore untyped local -import { queryEsSQL } from '../../../../../../plugins/canvas/server/lib/query_es_sql'; +import { queryEsSQL } from '../../../server/lib/query_es_sql'; /* eslint-enable */ import { ExpressionValueFilter } from '../../../types'; import { getFunctionHelp } from '../../../i18n'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/essql.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/essql.ts similarity index 94% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/essql.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/essql.ts index 7c9cb92ad009c..c64398d4b3a18 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/essql.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/essql.ts @@ -7,7 +7,7 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; /* eslint-disable */ // @ts-ignore untyped local -import { queryEsSQL } from '../../../../../../plugins/canvas/server/lib/query_es_sql'; +import { queryEsSQL } from '../../../server/lib/query_es_sql'; /* eslint-enable */ import { ExpressionValueFilter } from '../../../types'; import { getFunctionHelp } from '../../../i18n'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/get_field_names.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_field_names.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/get_field_names.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_field_names.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/is_column_reference.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/is_column_reference.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/is_column_reference.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/is_column_reference.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_expression_type.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_expression_type.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_expression_type.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_expression_type.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_field_names.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_field_names.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_field_names.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/get_field_names.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/is_column_reference.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/is_column_reference.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/is_column_reference.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries/lib/is_column_reference.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/elastic_logo.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/elastic_logo.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/elastic_logo.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/elastic_logo.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/elastic_outline.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/elastic_outline.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/elastic_outline.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/elastic_outline.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/API.md b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/API.md similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/API.md rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/API.md diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/index.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.colorhelpers.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.colorhelpers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.colorhelpers.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.colorhelpers.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.canvas.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.canvas.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.canvas.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.canvas.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.categories.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.categories.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.categories.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.categories.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.crosshair.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.crosshair.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.crosshair.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.crosshair.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.errorbars.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.errorbars.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.errorbars.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.errorbars.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.fillbetween.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.fillbetween.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.fillbetween.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.fillbetween.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.image.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.image.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.image.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.image.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.navigate.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.navigate.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.navigate.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.navigate.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.resize.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.resize.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.resize.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.resize.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.selection.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.selection.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.selection.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.selection.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.stack.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.stack.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.stack.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.stack.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.symbol.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.symbol.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.symbol.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.symbol.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.threshold.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.threshold.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.threshold.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.threshold.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.time.js b/x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.time.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.time.js rename to x-pack/plugins/canvas/canvas_plugin_src/lib/flot-charts/jquery.flot.time.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts b/x-pack/plugins/canvas/canvas_plugin_src/plugin.ts similarity index 90% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts rename to x-pack/plugins/canvas/canvas_plugin_src/plugin.ts index 4452e5e9e31fe..c9ce4d065968a 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/plugin.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/plugin.ts @@ -6,9 +6,9 @@ import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { CanvasSetup } from '../public'; -import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; -import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; -import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public'; +import { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; +import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; +import { Start as InspectorStart } from '../../../../src/plugins/inspector/public'; import { functions } from './functions/browser'; import { typeFunctions } from './expression_types'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/__snapshots__/advanced_filter.examples.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/__snapshots__/advanced_filter.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/__snapshots__/advanced_filter.examples.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/__snapshots__/advanced_filter.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/advanced_filter.examples.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/advanced_filter.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/advanced_filter.examples.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/__examples__/advanced_filter.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/advanced_filter.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/component/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/index.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/advanced_filter/index.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/debug.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/debug.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/debug.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/debug.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/__snapshots__/dropdown_filter.examples.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/__snapshots__/dropdown_filter.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/__snapshots__/dropdown_filter.examples.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/__snapshots__/dropdown_filter.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/dropdown_filter.examples.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/dropdown_filter.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/dropdown_filter.examples.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/__examples__/dropdown_filter.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/dropdown_filter.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/component/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/dropdown_filter/index.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx similarity index 94% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx index 1e8983a0ca5e5..0e0d5fd1953fe 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable.tsx @@ -6,17 +6,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { CoreStart } from '../../../../../../../src/core/public'; +import { CoreStart } from '../../../../../../src/core/public'; import { StartDeps } from '../../plugin'; import { IEmbeddable, EmbeddableFactory, EmbeddablePanel, EmbeddableFactoryNotFoundError, -} from '../../../../../../../src/plugins/embeddable/public'; +} from '../../../../../../src/plugins/embeddable/public'; import { EmbeddableExpression } from '../../expression_types/embeddable'; import { RendererStrings } from '../../../i18n'; -import { getSavedObjectFinder } from '../../../../../../../src/plugins/saved_objects/public'; +import { getSavedObjectFinder } from '../../../../../../src/plugins/saved_objects/public'; import { embeddableInputToExpression } from './embeddable_input_to_expression'; import { EmbeddableInput } from '../../expression_types'; import { RendererHandlers } from '../../../types'; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/embeddable_input_to_expression.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/lens.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts similarity index 96% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts index f9ff94ee7d8f1..e0e0aeaeea272 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.test.ts @@ -5,7 +5,7 @@ */ import { toExpression } from './map'; -import { MapEmbeddableInput } from '../../../../../maps/public'; +import { MapEmbeddableInput } from '../../../../../../legacy/plugins/maps/public'; import { fromExpression, Ast } from '@kbn/interpreter/common'; const baseSavedMapInput = { diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts similarity index 92% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts index e0cb71c17774c..1f9bec133488c 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/map.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { MapEmbeddableInput } from '../../../../../maps/public'; +import { MapEmbeddableInput } from '../../../../../../legacy/plugins/maps/public'; export function toExpression(input: MapEmbeddableInput): string { const expressionParts = [] as string[]; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.test.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/embeddable/input_type_to_expression/visualization.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/error/error.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/error/error.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/error/error.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/error/error.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/error/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/error/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/error/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/error/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/image.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/image.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/image.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/image.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js similarity index 92% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js index 126699534caad..a7b0f620cf710 100644 --- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/markdown/index.js @@ -7,7 +7,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { RendererStrings } from '../../../i18n'; -import { Markdown } from '../../../../../../../src/plugins/kibana_react/public'; +import { Markdown } from '../../../../../../src/plugins/kibana_react/public'; const { markdown: strings } = RendererStrings; diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/__snapshots__/metric.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/__snapshots__/metric.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/__snapshots__/metric.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/__snapshots__/metric.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/metric.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/metric.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/metric.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/__examples__/metric.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/metric.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/metric.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/component/metric.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/component/metric.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/metric/index.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/metric/index.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/pie/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/pie/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/pie/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/pie/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/pie/plugins/pie.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/pie/plugins/pie.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/pie/plugins/pie.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/pie/plugins/pie.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plot.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plot.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plot.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plot.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/size.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/size.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/size.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/size.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/text.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/text.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/text.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/plot/plugins/text.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/gauge.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/gauge.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/gauge.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/gauge.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_bar.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_bar.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_bar.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_bar.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_pill.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_pill.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_pill.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/horizontal_pill.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/semicircle.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/semicircle.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/semicircle.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/semicircle.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/unicorn.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/unicorn.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/unicorn.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/unicorn.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_bar.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_bar.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_bar.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_bar.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_pill.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_pill.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_pill.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/vertical_pill.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/wheel.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/wheel.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/wheel.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/progress/shapes/wheel.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/repeat_image.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/repeat_image.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/reveal_image/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/reveal_image/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/reveal_image/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/reveal_image/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/reveal_image/reveal_image.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/reveal_image/reveal_image.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/reveal_image/reveal_image.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/reveal_image/reveal_image.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/index.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow_multi.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow_multi.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow_multi.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/arrow_multi.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/bookmark.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/bookmark.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/bookmark.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/bookmark.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/circle.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/circle.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/circle.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/circle.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/cross.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/cross.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/cross.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/cross.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/hexagon.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/hexagon.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/hexagon.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/hexagon.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/kite.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/kite.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/kite.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/kite.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/pentagon.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/pentagon.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/pentagon.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/pentagon.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/rhombus.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/rhombus.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/rhombus.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/rhombus.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/semicircle.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/semicircle.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/semicircle.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/semicircle.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/speech_bubble.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/speech_bubble.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/speech_bubble.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/speech_bubble.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/square.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/square.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/square.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/square.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/star.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/star.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/star.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/star.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/tag.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/tag.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/tag.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/tag.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle_right.svg b/x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle_right.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle_right.svg rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/shape/shapes/triangle_right.svg diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/table.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/table.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/table.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/table.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/text.js b/x-pack/plugins/canvas/canvas_plugin_src/renderers/text.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/text.js rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/text.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.examples.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.examples.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/__snapshots__/time_filter.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/time_filter.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/time_filter.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/time_filter.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/__examples__/time_filter.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/index.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/index.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/components/time_filter.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/index.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/time_filter.scss b/x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/time_filter.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/renderers/time_filter/time_filter.scss rename to x-pack/plugins/canvas/canvas_plugin_src/renderers/time_filter/time_filter.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/templates/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/templates/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/pitch_presentation.json b/x-pack/plugins/canvas/canvas_plugin_src/templates/pitch_presentation.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/pitch_presentation.json rename to x-pack/plugins/canvas/canvas_plugin_src/templates/pitch_presentation.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/status_report.json b/x-pack/plugins/canvas/canvas_plugin_src/templates/status_report.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/status_report.json rename to x-pack/plugins/canvas/canvas_plugin_src/templates/status_report.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/summary_report.json b/x-pack/plugins/canvas/canvas_plugin_src/templates/summary_report.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/summary_report.json rename to x-pack/plugins/canvas/canvas_plugin_src/templates/summary_report.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/theme_dark.json b/x-pack/plugins/canvas/canvas_plugin_src/templates/theme_dark.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/theme_dark.json rename to x-pack/plugins/canvas/canvas_plugin_src/templates/theme_dark.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/theme_light.json b/x-pack/plugins/canvas/canvas_plugin_src/templates/theme_light.json similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/templates/theme_light.json rename to x-pack/plugins/canvas/canvas_plugin_src/templates/theme_light.json diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/extended_template.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/extended_template.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/extended_template.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/extended_template.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/simple_template.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/simple_template.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/simple_template.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/__snapshots__/simple_template.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/extended_template.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/extended_template.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/extended_template.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/extended_template.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/simple_template.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/simple_template.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/simple_template.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/__examples__/simple_template.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/extended_template.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/extended_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/extended_template.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/extended_template.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/simple_template.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/simple_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/simple_template.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/axis_config/simple_template.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/simple_math_function.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/simple_math_function.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/simple_math_function.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/simple_math_function.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/__snapshots__/date_format.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/__snapshots__/date_format.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/__snapshots__/date_format.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/__snapshots__/date_format.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/date_format.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/date_format.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/date_format.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/__examples__/date_format.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/date_format.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/date_format.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/date_format.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/date_format.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/date_format/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/filter_group.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/filter_group.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/filter_group.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/filter_group.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/file.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/file.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/file.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/file.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/link.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/link.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/link.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/forms/link.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/image_upload.scss b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/image_upload.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/image_upload.scss rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/image_upload.scss diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/__snapshots__/number_format.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/__snapshots__/number_format.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/__snapshots__/number_format.stories.storyshot rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/__snapshots__/number_format.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/number_format.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/number_format.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/number_format.stories.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/__examples__/number_format.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/number_format.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/number_format.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/number_format.tsx rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/number_format/number_format.tsx diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/percentage.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/percentage.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/percentage.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/percentage.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/range.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/range.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/range.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/range.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/select.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/select.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/select.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/select.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/string.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/string.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/string.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/string.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/textarea.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/textarea.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/textarea.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/textarea.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/demodata.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/esdocs.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/essql.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/datasources/timelion.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/models/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/models/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/math.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/models/math.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/math.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/models/math.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/point_series.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/models/point_series.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/models/point_series.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/models/point_series.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/tags/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/tags/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/presentation.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/tags/presentation.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/presentation.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/tags/presentation.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/report.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/tags/report.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/report.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/tags/report.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/formatdate.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/formatdate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/formatdate.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/formatdate.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/formatnumber.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/formatnumber.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/formatnumber.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/formatnumber.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/index.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/index.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/rounddate.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/rounddate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/rounddate.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/rounddate.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/sort.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/sort.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/transforms/sort.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/transforms/sort.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/dropdownControl.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/dropdownControl.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/dropdownControl.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/dropdownControl.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/getCell.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/getCell.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/getCell.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/getCell.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/image.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/image.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/index.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/index.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/index.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/markdown.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/markdown.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/markdown.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/metric.ts b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/metric.ts rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/metric.ts diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/pie.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/pie.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/pie.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/plot.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/plot.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/plot.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/plot.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/progress.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/progress.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/render.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/render.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/render.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/render.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/repeatImage.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/repeatImage.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/repeatImage.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/repeatImage.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/revealImage.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/revealImage.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/revealImage.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/revealImage.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/shape.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/shape.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/shape.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/table.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/table.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/table.js diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/timefilterControl.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/timefilterControl.js similarity index 100% rename from x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/views/timefilterControl.js rename to x-pack/plugins/canvas/canvas_plugin_src/uis/views/timefilterControl.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/autocomplete.test.ts b/x-pack/plugins/canvas/common/lib/autocomplete.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/autocomplete.test.ts rename to x-pack/plugins/canvas/common/lib/autocomplete.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/autocomplete.ts b/x-pack/plugins/canvas/common/lib/autocomplete.ts similarity index 99% rename from x-pack/legacy/plugins/canvas/common/lib/autocomplete.ts rename to x-pack/plugins/canvas/common/lib/autocomplete.ts index 50341c977d6d9..5ee4d2104a0f7 100644 --- a/x-pack/legacy/plugins/canvas/common/lib/autocomplete.ts +++ b/x-pack/plugins/canvas/common/lib/autocomplete.ts @@ -14,7 +14,7 @@ import { ExpressionFunction, ExpressionFunctionParameter, getByAlias, -} from '../../../../../../src/plugins/expressions'; +} from '../../../../../src/plugins/expressions'; const MARKER = 'CANVAS_SUGGESTION_MARKER'; diff --git a/x-pack/legacy/plugins/canvas/common/lib/constants.ts b/x-pack/plugins/canvas/common/lib/constants.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/constants.ts rename to x-pack/plugins/canvas/common/lib/constants.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/datatable/index.js b/x-pack/plugins/canvas/common/lib/datatable/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/datatable/index.js rename to x-pack/plugins/canvas/common/lib/datatable/index.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/datatable/query.js b/x-pack/plugins/canvas/common/lib/datatable/query.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/datatable/query.js rename to x-pack/plugins/canvas/common/lib/datatable/query.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/dataurl.test.ts b/x-pack/plugins/canvas/common/lib/dataurl.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/dataurl.test.ts rename to x-pack/plugins/canvas/common/lib/dataurl.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/dataurl.ts b/x-pack/plugins/canvas/common/lib/dataurl.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/dataurl.ts rename to x-pack/plugins/canvas/common/lib/dataurl.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/errors.js b/x-pack/plugins/canvas/common/lib/errors.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/errors.js rename to x-pack/plugins/canvas/common/lib/errors.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/errors.test.js b/x-pack/plugins/canvas/common/lib/errors.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/errors.test.js rename to x-pack/plugins/canvas/common/lib/errors.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/expression_form_handlers.js b/x-pack/plugins/canvas/common/lib/expression_form_handlers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/expression_form_handlers.js rename to x-pack/plugins/canvas/common/lib/expression_form_handlers.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/expression_form_handlers.test.js b/x-pack/plugins/canvas/common/lib/expression_form_handlers.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/expression_form_handlers.test.js rename to x-pack/plugins/canvas/common/lib/expression_form_handlers.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/fetch.test.ts b/x-pack/plugins/canvas/common/lib/fetch.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/fetch.test.ts rename to x-pack/plugins/canvas/common/lib/fetch.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/fetch.ts b/x-pack/plugins/canvas/common/lib/fetch.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/fetch.ts rename to x-pack/plugins/canvas/common/lib/fetch.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/fonts.ts b/x-pack/plugins/canvas/common/lib/fonts.ts similarity index 77% rename from x-pack/legacy/plugins/canvas/common/lib/fonts.ts rename to x-pack/plugins/canvas/common/lib/fonts.ts index 14cc403af86ac..e0d39f65f01c2 100644 --- a/x-pack/legacy/plugins/canvas/common/lib/fonts.ts +++ b/x-pack/plugins/canvas/common/lib/fonts.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from '../../../../../../src/plugins/expressions/common/fonts'; +export * from '../../../../../src/plugins/expressions/common/fonts'; diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_colors_from_palette.js b/x-pack/plugins/canvas/common/lib/get_colors_from_palette.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_colors_from_palette.js rename to x-pack/plugins/canvas/common/lib/get_colors_from_palette.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_colors_from_palette.test.js b/x-pack/plugins/canvas/common/lib/get_colors_from_palette.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_colors_from_palette.test.js rename to x-pack/plugins/canvas/common/lib/get_colors_from_palette.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_field_type.test.ts b/x-pack/plugins/canvas/common/lib/get_field_type.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_field_type.test.ts rename to x-pack/plugins/canvas/common/lib/get_field_type.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_field_type.ts b/x-pack/plugins/canvas/common/lib/get_field_type.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_field_type.ts rename to x-pack/plugins/canvas/common/lib/get_field_type.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_id.ts b/x-pack/plugins/canvas/common/lib/get_id.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_id.ts rename to x-pack/plugins/canvas/common/lib/get_id.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_legend_config.js b/x-pack/plugins/canvas/common/lib/get_legend_config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_legend_config.js rename to x-pack/plugins/canvas/common/lib/get_legend_config.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/get_legend_config.test.js b/x-pack/plugins/canvas/common/lib/get_legend_config.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/get_legend_config.test.js rename to x-pack/plugins/canvas/common/lib/get_legend_config.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/handlebars.js b/x-pack/plugins/canvas/common/lib/handlebars.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/handlebars.js rename to x-pack/plugins/canvas/common/lib/handlebars.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/handlebars.test.js b/x-pack/plugins/canvas/common/lib/handlebars.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/handlebars.test.js rename to x-pack/plugins/canvas/common/lib/handlebars.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/hex_to_rgb.test.ts b/x-pack/plugins/canvas/common/lib/hex_to_rgb.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/hex_to_rgb.test.ts rename to x-pack/plugins/canvas/common/lib/hex_to_rgb.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/hex_to_rgb.ts b/x-pack/plugins/canvas/common/lib/hex_to_rgb.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/hex_to_rgb.ts rename to x-pack/plugins/canvas/common/lib/hex_to_rgb.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/httpurl.test.ts b/x-pack/plugins/canvas/common/lib/httpurl.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/httpurl.test.ts rename to x-pack/plugins/canvas/common/lib/httpurl.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/httpurl.ts b/x-pack/plugins/canvas/common/lib/httpurl.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/httpurl.ts rename to x-pack/plugins/canvas/common/lib/httpurl.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/index.ts b/x-pack/plugins/canvas/common/lib/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/index.ts rename to x-pack/plugins/canvas/common/lib/index.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/missing_asset.js b/x-pack/plugins/canvas/common/lib/missing_asset.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/missing_asset.js rename to x-pack/plugins/canvas/common/lib/missing_asset.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/palettes.js b/x-pack/plugins/canvas/common/lib/palettes.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/palettes.js rename to x-pack/plugins/canvas/common/lib/palettes.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/pivot_object_array.test.ts b/x-pack/plugins/canvas/common/lib/pivot_object_array.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/pivot_object_array.test.ts rename to x-pack/plugins/canvas/common/lib/pivot_object_array.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/pivot_object_array.ts b/x-pack/plugins/canvas/common/lib/pivot_object_array.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/pivot_object_array.ts rename to x-pack/plugins/canvas/common/lib/pivot_object_array.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/resolve_dataurl.js b/x-pack/plugins/canvas/common/lib/resolve_dataurl.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/resolve_dataurl.js rename to x-pack/plugins/canvas/common/lib/resolve_dataurl.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/resolve_dataurl.test.js b/x-pack/plugins/canvas/common/lib/resolve_dataurl.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/resolve_dataurl.test.js rename to x-pack/plugins/canvas/common/lib/resolve_dataurl.test.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/time_units.ts b/x-pack/plugins/canvas/common/lib/time_units.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/time_units.ts rename to x-pack/plugins/canvas/common/lib/time_units.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/unquote_string.test.ts b/x-pack/plugins/canvas/common/lib/unquote_string.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/unquote_string.test.ts rename to x-pack/plugins/canvas/common/lib/unquote_string.test.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/unquote_string.ts b/x-pack/plugins/canvas/common/lib/unquote_string.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/unquote_string.ts rename to x-pack/plugins/canvas/common/lib/unquote_string.ts diff --git a/x-pack/legacy/plugins/canvas/common/lib/url.js b/x-pack/plugins/canvas/common/lib/url.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/url.js rename to x-pack/plugins/canvas/common/lib/url.js diff --git a/x-pack/legacy/plugins/canvas/common/lib/url.test.js b/x-pack/plugins/canvas/common/lib/url.test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/common/lib/url.test.js rename to x-pack/plugins/canvas/common/lib/url.test.js diff --git a/x-pack/legacy/plugins/canvas/i18n/README.md b/x-pack/plugins/canvas/i18n/README.md similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/README.md rename to x-pack/plugins/canvas/i18n/README.md diff --git a/x-pack/legacy/plugins/canvas/i18n/capabilities.ts b/x-pack/plugins/canvas/i18n/capabilities.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/capabilities.ts rename to x-pack/plugins/canvas/i18n/capabilities.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/components.ts b/x-pack/plugins/canvas/i18n/components.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/components.ts rename to x-pack/plugins/canvas/i18n/components.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/constants.ts b/x-pack/plugins/canvas/i18n/constants.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/constants.ts rename to x-pack/plugins/canvas/i18n/constants.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts b/x-pack/plugins/canvas/i18n/elements/apply_strings.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts rename to x-pack/plugins/canvas/i18n/elements/apply_strings.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts b/x-pack/plugins/canvas/i18n/elements/element_strings.test.ts similarity index 95% rename from x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts rename to x-pack/plugins/canvas/i18n/elements/element_strings.test.ts index c28229bdab33f..1eff73c1525b1 100644 --- a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts +++ b/x-pack/plugins/canvas/i18n/elements/element_strings.test.ts @@ -5,7 +5,7 @@ */ import { getElementStrings } from './element_strings'; import { initializeElements } from '../../canvas_plugin_src/elements'; -import { coreMock } from '../../../../../../src/core/public/mocks'; +import { coreMock } from '../../../../../src/core/public/mocks'; const elementSpecs = initializeElements(coreMock.createSetup() as any, {} as any); diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts b/x-pack/plugins/canvas/i18n/elements/element_strings.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts rename to x-pack/plugins/canvas/i18n/elements/element_strings.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/index.ts b/x-pack/plugins/canvas/i18n/elements/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/elements/index.ts rename to x-pack/plugins/canvas/i18n/elements/index.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/errors.ts b/x-pack/plugins/canvas/i18n/errors.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/errors.ts rename to x-pack/plugins/canvas/i18n/errors.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/expression_types.ts b/x-pack/plugins/canvas/i18n/expression_types.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/expression_types.ts rename to x-pack/plugins/canvas/i18n/expression_types.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/all.ts b/x-pack/plugins/canvas/i18n/functions/dict/all.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/all.ts rename to x-pack/plugins/canvas/i18n/functions/dict/all.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts b/x-pack/plugins/canvas/i18n/functions/dict/alter_column.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts rename to x-pack/plugins/canvas/i18n/functions/dict/alter_column.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/any.ts b/x-pack/plugins/canvas/i18n/functions/dict/any.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/any.ts rename to x-pack/plugins/canvas/i18n/functions/dict/any.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/as.ts b/x-pack/plugins/canvas/i18n/functions/dict/as.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/as.ts rename to x-pack/plugins/canvas/i18n/functions/dict/as.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/asset.ts b/x-pack/plugins/canvas/i18n/functions/dict/asset.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/asset.ts rename to x-pack/plugins/canvas/i18n/functions/dict/asset.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/axis_config.ts b/x-pack/plugins/canvas/i18n/functions/dict/axis_config.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/axis_config.ts rename to x-pack/plugins/canvas/i18n/functions/dict/axis_config.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/case.ts b/x-pack/plugins/canvas/i18n/functions/dict/case.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/case.ts rename to x-pack/plugins/canvas/i18n/functions/dict/case.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/clear.ts b/x-pack/plugins/canvas/i18n/functions/dict/clear.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/clear.ts rename to x-pack/plugins/canvas/i18n/functions/dict/clear.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/columns.ts b/x-pack/plugins/canvas/i18n/functions/dict/columns.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/columns.ts rename to x-pack/plugins/canvas/i18n/functions/dict/columns.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/compare.ts b/x-pack/plugins/canvas/i18n/functions/dict/compare.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/compare.ts rename to x-pack/plugins/canvas/i18n/functions/dict/compare.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/container_style.ts b/x-pack/plugins/canvas/i18n/functions/dict/container_style.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/container_style.ts rename to x-pack/plugins/canvas/i18n/functions/dict/container_style.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/context.ts b/x-pack/plugins/canvas/i18n/functions/dict/context.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/context.ts rename to x-pack/plugins/canvas/i18n/functions/dict/context.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/csv.ts b/x-pack/plugins/canvas/i18n/functions/dict/csv.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/csv.ts rename to x-pack/plugins/canvas/i18n/functions/dict/csv.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/date.ts b/x-pack/plugins/canvas/i18n/functions/dict/date.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/date.ts rename to x-pack/plugins/canvas/i18n/functions/dict/date.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts b/x-pack/plugins/canvas/i18n/functions/dict/demodata.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/demodata.ts rename to x-pack/plugins/canvas/i18n/functions/dict/demodata.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/do.ts b/x-pack/plugins/canvas/i18n/functions/dict/do.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/do.ts rename to x-pack/plugins/canvas/i18n/functions/dict/do.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/dropdown_control.ts b/x-pack/plugins/canvas/i18n/functions/dict/dropdown_control.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/dropdown_control.ts rename to x-pack/plugins/canvas/i18n/functions/dict/dropdown_control.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/eq.ts b/x-pack/plugins/canvas/i18n/functions/dict/eq.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/eq.ts rename to x-pack/plugins/canvas/i18n/functions/dict/eq.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/escount.ts b/x-pack/plugins/canvas/i18n/functions/dict/escount.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/escount.ts rename to x-pack/plugins/canvas/i18n/functions/dict/escount.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/esdocs.ts b/x-pack/plugins/canvas/i18n/functions/dict/esdocs.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/esdocs.ts rename to x-pack/plugins/canvas/i18n/functions/dict/esdocs.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/essql.ts b/x-pack/plugins/canvas/i18n/functions/dict/essql.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/essql.ts rename to x-pack/plugins/canvas/i18n/functions/dict/essql.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/exactly.ts b/x-pack/plugins/canvas/i18n/functions/dict/exactly.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/exactly.ts rename to x-pack/plugins/canvas/i18n/functions/dict/exactly.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/filterrows.ts b/x-pack/plugins/canvas/i18n/functions/dict/filterrows.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/filterrows.ts rename to x-pack/plugins/canvas/i18n/functions/dict/filterrows.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/filters.ts b/x-pack/plugins/canvas/i18n/functions/dict/filters.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/filters.ts rename to x-pack/plugins/canvas/i18n/functions/dict/filters.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatdate.ts b/x-pack/plugins/canvas/i18n/functions/dict/formatdate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/formatdate.ts rename to x-pack/plugins/canvas/i18n/functions/dict/formatdate.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts b/x-pack/plugins/canvas/i18n/functions/dict/formatnumber.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/formatnumber.ts rename to x-pack/plugins/canvas/i18n/functions/dict/formatnumber.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/get_cell.ts b/x-pack/plugins/canvas/i18n/functions/dict/get_cell.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/get_cell.ts rename to x-pack/plugins/canvas/i18n/functions/dict/get_cell.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/gt.ts b/x-pack/plugins/canvas/i18n/functions/dict/gt.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/gt.ts rename to x-pack/plugins/canvas/i18n/functions/dict/gt.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/gte.ts b/x-pack/plugins/canvas/i18n/functions/dict/gte.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/gte.ts rename to x-pack/plugins/canvas/i18n/functions/dict/gte.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/head.ts b/x-pack/plugins/canvas/i18n/functions/dict/head.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/head.ts rename to x-pack/plugins/canvas/i18n/functions/dict/head.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/if.ts b/x-pack/plugins/canvas/i18n/functions/dict/if.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/if.ts rename to x-pack/plugins/canvas/i18n/functions/dict/if.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/image.ts b/x-pack/plugins/canvas/i18n/functions/dict/image.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/image.ts rename to x-pack/plugins/canvas/i18n/functions/dict/image.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/join_rows.ts b/x-pack/plugins/canvas/i18n/functions/dict/join_rows.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/join_rows.ts rename to x-pack/plugins/canvas/i18n/functions/dict/join_rows.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/location.ts b/x-pack/plugins/canvas/i18n/functions/dict/location.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/location.ts rename to x-pack/plugins/canvas/i18n/functions/dict/location.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/lt.ts b/x-pack/plugins/canvas/i18n/functions/dict/lt.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/lt.ts rename to x-pack/plugins/canvas/i18n/functions/dict/lt.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/lte.ts b/x-pack/plugins/canvas/i18n/functions/dict/lte.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/lte.ts rename to x-pack/plugins/canvas/i18n/functions/dict/lte.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/map_center.ts b/x-pack/plugins/canvas/i18n/functions/dict/map_center.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/map_center.ts rename to x-pack/plugins/canvas/i18n/functions/dict/map_center.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/map_column.ts b/x-pack/plugins/canvas/i18n/functions/dict/map_column.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/map_column.ts rename to x-pack/plugins/canvas/i18n/functions/dict/map_column.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/markdown.ts b/x-pack/plugins/canvas/i18n/functions/dict/markdown.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/markdown.ts rename to x-pack/plugins/canvas/i18n/functions/dict/markdown.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/math.ts b/x-pack/plugins/canvas/i18n/functions/dict/math.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/math.ts rename to x-pack/plugins/canvas/i18n/functions/dict/math.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts b/x-pack/plugins/canvas/i18n/functions/dict/metric.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/metric.ts rename to x-pack/plugins/canvas/i18n/functions/dict/metric.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/neq.ts b/x-pack/plugins/canvas/i18n/functions/dict/neq.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/neq.ts rename to x-pack/plugins/canvas/i18n/functions/dict/neq.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/palette.ts b/x-pack/plugins/canvas/i18n/functions/dict/palette.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/palette.ts rename to x-pack/plugins/canvas/i18n/functions/dict/palette.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/pie.ts b/x-pack/plugins/canvas/i18n/functions/dict/pie.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/pie.ts rename to x-pack/plugins/canvas/i18n/functions/dict/pie.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/plot.ts b/x-pack/plugins/canvas/i18n/functions/dict/plot.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/plot.ts rename to x-pack/plugins/canvas/i18n/functions/dict/plot.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/ply.ts b/x-pack/plugins/canvas/i18n/functions/dict/ply.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/ply.ts rename to x-pack/plugins/canvas/i18n/functions/dict/ply.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/pointseries.ts b/x-pack/plugins/canvas/i18n/functions/dict/pointseries.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/pointseries.ts rename to x-pack/plugins/canvas/i18n/functions/dict/pointseries.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/progress.ts b/x-pack/plugins/canvas/i18n/functions/dict/progress.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/progress.ts rename to x-pack/plugins/canvas/i18n/functions/dict/progress.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/render.ts b/x-pack/plugins/canvas/i18n/functions/dict/render.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/render.ts rename to x-pack/plugins/canvas/i18n/functions/dict/render.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/repeat_image.ts b/x-pack/plugins/canvas/i18n/functions/dict/repeat_image.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/repeat_image.ts rename to x-pack/plugins/canvas/i18n/functions/dict/repeat_image.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/replace.ts b/x-pack/plugins/canvas/i18n/functions/dict/replace.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/replace.ts rename to x-pack/plugins/canvas/i18n/functions/dict/replace.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/reveal_image.ts b/x-pack/plugins/canvas/i18n/functions/dict/reveal_image.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/reveal_image.ts rename to x-pack/plugins/canvas/i18n/functions/dict/reveal_image.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/rounddate.ts b/x-pack/plugins/canvas/i18n/functions/dict/rounddate.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/rounddate.ts rename to x-pack/plugins/canvas/i18n/functions/dict/rounddate.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/row_count.ts b/x-pack/plugins/canvas/i18n/functions/dict/row_count.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/row_count.ts rename to x-pack/plugins/canvas/i18n/functions/dict/row_count.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_lens.ts b/x-pack/plugins/canvas/i18n/functions/dict/saved_lens.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_lens.ts rename to x-pack/plugins/canvas/i18n/functions/dict/saved_lens.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_map.ts b/x-pack/plugins/canvas/i18n/functions/dict/saved_map.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_map.ts rename to x-pack/plugins/canvas/i18n/functions/dict/saved_map.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_search.ts b/x-pack/plugins/canvas/i18n/functions/dict/saved_search.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_search.ts rename to x-pack/plugins/canvas/i18n/functions/dict/saved_search.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts b/x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_visualization.ts rename to x-pack/plugins/canvas/i18n/functions/dict/saved_visualization.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/series_style.ts b/x-pack/plugins/canvas/i18n/functions/dict/series_style.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/series_style.ts rename to x-pack/plugins/canvas/i18n/functions/dict/series_style.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/shape.ts b/x-pack/plugins/canvas/i18n/functions/dict/shape.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/shape.ts rename to x-pack/plugins/canvas/i18n/functions/dict/shape.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/sort.ts b/x-pack/plugins/canvas/i18n/functions/dict/sort.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/sort.ts rename to x-pack/plugins/canvas/i18n/functions/dict/sort.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/static_column.ts b/x-pack/plugins/canvas/i18n/functions/dict/static_column.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/static_column.ts rename to x-pack/plugins/canvas/i18n/functions/dict/static_column.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/string.ts b/x-pack/plugins/canvas/i18n/functions/dict/string.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/string.ts rename to x-pack/plugins/canvas/i18n/functions/dict/string.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/switch.ts b/x-pack/plugins/canvas/i18n/functions/dict/switch.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/switch.ts rename to x-pack/plugins/canvas/i18n/functions/dict/switch.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/table.ts b/x-pack/plugins/canvas/i18n/functions/dict/table.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/table.ts rename to x-pack/plugins/canvas/i18n/functions/dict/table.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/tail.ts b/x-pack/plugins/canvas/i18n/functions/dict/tail.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/tail.ts rename to x-pack/plugins/canvas/i18n/functions/dict/tail.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/time_range.ts b/x-pack/plugins/canvas/i18n/functions/dict/time_range.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/time_range.ts rename to x-pack/plugins/canvas/i18n/functions/dict/time_range.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/timefilter.ts b/x-pack/plugins/canvas/i18n/functions/dict/timefilter.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/timefilter.ts rename to x-pack/plugins/canvas/i18n/functions/dict/timefilter.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/timefilter_control.ts b/x-pack/plugins/canvas/i18n/functions/dict/timefilter_control.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/timefilter_control.ts rename to x-pack/plugins/canvas/i18n/functions/dict/timefilter_control.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/timelion.ts b/x-pack/plugins/canvas/i18n/functions/dict/timelion.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/timelion.ts rename to x-pack/plugins/canvas/i18n/functions/dict/timelion.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/to.ts b/x-pack/plugins/canvas/i18n/functions/dict/to.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/to.ts rename to x-pack/plugins/canvas/i18n/functions/dict/to.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/urlparam.ts b/x-pack/plugins/canvas/i18n/functions/dict/urlparam.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/dict/urlparam.ts rename to x-pack/plugins/canvas/i18n/functions/dict/urlparam.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/function_errors.ts b/x-pack/plugins/canvas/i18n/functions/function_errors.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/function_errors.ts rename to x-pack/plugins/canvas/i18n/functions/function_errors.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts b/x-pack/plugins/canvas/i18n/functions/function_help.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts rename to x-pack/plugins/canvas/i18n/functions/function_help.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/index.ts b/x-pack/plugins/canvas/i18n/functions/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/functions/index.ts rename to x-pack/plugins/canvas/i18n/functions/index.ts diff --git a/x-pack/plugins/canvas/i18n/index.ts b/x-pack/plugins/canvas/i18n/index.ts index 8a65a75c0cfb9..864311d34aca0 100644 --- a/x-pack/plugins/canvas/i18n/index.ts +++ b/x-pack/plugins/canvas/i18n/index.ts @@ -4,4 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from '../../../legacy/plugins/canvas/i18n'; +export * from './capabilities'; +export * from './components'; +export * from './constants'; +export * from './errors'; +export * from './expression_types'; +export * from './elements'; +export * from './functions'; +export * from './renderers'; +export * from './shortcuts'; +export * from './tags'; +export * from './transitions'; +export * from './ui'; +export * from './units'; diff --git a/x-pack/legacy/plugins/canvas/i18n/renderers.ts b/x-pack/plugins/canvas/i18n/renderers.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/renderers.ts rename to x-pack/plugins/canvas/i18n/renderers.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/shortcuts.ts b/x-pack/plugins/canvas/i18n/shortcuts.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/shortcuts.ts rename to x-pack/plugins/canvas/i18n/shortcuts.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/tags.ts b/x-pack/plugins/canvas/i18n/tags.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/tags.ts rename to x-pack/plugins/canvas/i18n/tags.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/templates/apply_strings.ts b/x-pack/plugins/canvas/i18n/templates/apply_strings.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/templates/apply_strings.ts rename to x-pack/plugins/canvas/i18n/templates/apply_strings.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/templates/index.ts b/x-pack/plugins/canvas/i18n/templates/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/templates/index.ts rename to x-pack/plugins/canvas/i18n/templates/index.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/templates/template_strings.test.ts b/x-pack/plugins/canvas/i18n/templates/template_strings.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/templates/template_strings.test.ts rename to x-pack/plugins/canvas/i18n/templates/template_strings.test.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/templates/template_strings.ts b/x-pack/plugins/canvas/i18n/templates/template_strings.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/templates/template_strings.ts rename to x-pack/plugins/canvas/i18n/templates/template_strings.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/transitions.ts b/x-pack/plugins/canvas/i18n/transitions.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/transitions.ts rename to x-pack/plugins/canvas/i18n/transitions.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/ui.ts b/x-pack/plugins/canvas/i18n/ui.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/ui.ts rename to x-pack/plugins/canvas/i18n/ui.ts diff --git a/x-pack/legacy/plugins/canvas/i18n/units.ts b/x-pack/plugins/canvas/i18n/units.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/i18n/units.ts rename to x-pack/plugins/canvas/i18n/units.ts diff --git a/x-pack/legacy/plugins/canvas/images/canvas.png b/x-pack/plugins/canvas/images/canvas.png similarity index 100% rename from x-pack/legacy/plugins/canvas/images/canvas.png rename to x-pack/plugins/canvas/images/canvas.png diff --git a/x-pack/legacy/plugins/canvas/images/canvas.svg b/x-pack/plugins/canvas/images/canvas.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/images/canvas.svg rename to x-pack/plugins/canvas/images/canvas.svg diff --git a/x-pack/legacy/plugins/canvas/images/canvas_blank.svg b/x-pack/plugins/canvas/images/canvas_blank.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/images/canvas_blank.svg rename to x-pack/plugins/canvas/images/canvas_blank.svg diff --git a/x-pack/legacy/plugins/canvas/images/icon_black.svg b/x-pack/plugins/canvas/images/icon_black.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/images/icon_black.svg rename to x-pack/plugins/canvas/images/icon_black.svg diff --git a/x-pack/legacy/plugins/canvas/images/logo.gif b/x-pack/plugins/canvas/images/logo.gif similarity index 100% rename from x-pack/legacy/plugins/canvas/images/logo.gif rename to x-pack/plugins/canvas/images/logo.gif diff --git a/x-pack/legacy/plugins/canvas/public/__tests__/setup.js b/x-pack/plugins/canvas/public/__tests__/setup.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/__tests__/setup.js rename to x-pack/plugins/canvas/public/__tests__/setup.js diff --git a/x-pack/legacy/plugins/canvas/public/application.tsx b/x-pack/plugins/canvas/public/application.tsx similarity index 94% rename from x-pack/legacy/plugins/canvas/public/application.tsx rename to x-pack/plugins/canvas/public/application.tsx index 8ee65c3386afc..284023e74d137 100644 --- a/x-pack/legacy/plugins/canvas/public/application.tsx +++ b/x-pack/plugins/canvas/public/application.tsx @@ -16,7 +16,7 @@ import { AppMountParameters, CoreStart, CoreSetup } from 'kibana/public'; import { CanvasStartDeps, CanvasSetupDeps } from './plugin'; // @ts-ignore Untyped local import { App } from './components/app'; -import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; +import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; import { initInterpreter, resetInterpreter } from './lib/run_interpreter'; import { registerLanguage } from './lib/monaco_language_def'; import { SetupRegistries } from './plugin_api'; @@ -26,9 +26,9 @@ import { getDocumentationLinks } from './lib/documentation_links'; import { HelpMenu } from './components/help_menu/help_menu'; import { createStore, destroyStore } from './store'; -import { VALUE_CLICK_TRIGGER, ActionByType } from '../../../../../src/plugins/ui_actions/public'; +import { VALUE_CLICK_TRIGGER, ActionByType } from '../../../../src/plugins/ui_actions/public'; /* eslint-disable */ -import { ACTION_VALUE_CLICK } from '../../../../../src/plugins/data/public/actions/value_click_action'; +import { ACTION_VALUE_CLICK } from '../../../../src/plugins/data/public/actions/value_click_action'; /* eslint-enable */ import { init as initStatsReporter } from './lib/ui_metric'; diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap b/x-pack/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap rename to x-pack/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx b/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx rename to x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js b/x-pack/plugins/canvas/public/apps/export/export/export_app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.js rename to x-pack/plugins/canvas/public/apps/export/export/export_app.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.scss b/x-pack/plugins/canvas/public/apps/export/export/export_app.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/export_app.scss rename to x-pack/plugins/canvas/public/apps/export/export/export_app.scss diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/index.js b/x-pack/plugins/canvas/public/apps/export/export/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/index.js rename to x-pack/plugins/canvas/public/apps/export/export/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/export/load_workpad.js b/x-pack/plugins/canvas/public/apps/export/export/load_workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/export/load_workpad.js rename to x-pack/plugins/canvas/public/apps/export/export/load_workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/index.js b/x-pack/plugins/canvas/public/apps/export/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/index.js rename to x-pack/plugins/canvas/public/apps/export/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/export/routes.js b/x-pack/plugins/canvas/public/apps/export/routes.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/export/routes.js rename to x-pack/plugins/canvas/public/apps/export/routes.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/home/home_app/home_app.js b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/home/home_app/home_app.js rename to x-pack/plugins/canvas/public/apps/home/home_app/home_app.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/home/home_app/home_app.scss b/x-pack/plugins/canvas/public/apps/home/home_app/home_app.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/home/home_app/home_app.scss rename to x-pack/plugins/canvas/public/apps/home/home_app/home_app.scss diff --git a/x-pack/legacy/plugins/canvas/public/apps/home/home_app/index.js b/x-pack/plugins/canvas/public/apps/home/home_app/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/home/home_app/index.js rename to x-pack/plugins/canvas/public/apps/home/home_app/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/home/index.js b/x-pack/plugins/canvas/public/apps/home/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/home/index.js rename to x-pack/plugins/canvas/public/apps/home/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/home/routes.js b/x-pack/plugins/canvas/public/apps/home/routes.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/home/routes.js rename to x-pack/plugins/canvas/public/apps/home/routes.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/index.js b/x-pack/plugins/canvas/public/apps/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/index.js rename to x-pack/plugins/canvas/public/apps/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/index.js b/x-pack/plugins/canvas/public/apps/workpad/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/index.js rename to x-pack/plugins/canvas/public/apps/workpad/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/routes.js b/x-pack/plugins/canvas/public/apps/workpad/routes.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/routes.js rename to x-pack/plugins/canvas/public/apps/workpad/routes.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/index.js b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/index.js rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/index.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/load_workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.js diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.test.tsx diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx b/x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx rename to x-pack/plugins/canvas/public/apps/workpad/workpad_app/workpad_telemetry.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/alignment_guide/alignment_guide.js b/x-pack/plugins/canvas/public/components/alignment_guide/alignment_guide.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/alignment_guide/alignment_guide.js rename to x-pack/plugins/canvas/public/components/alignment_guide/alignment_guide.js diff --git a/x-pack/legacy/plugins/canvas/public/components/alignment_guide/alignment_guide.scss b/x-pack/plugins/canvas/public/components/alignment_guide/alignment_guide.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/alignment_guide/alignment_guide.scss rename to x-pack/plugins/canvas/public/components/alignment_guide/alignment_guide.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/alignment_guide/index.js b/x-pack/plugins/canvas/public/components/alignment_guide/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/alignment_guide/index.js rename to x-pack/plugins/canvas/public/components/alignment_guide/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/app/app.js b/x-pack/plugins/canvas/public/components/app/app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/app/app.js rename to x-pack/plugins/canvas/public/components/app/app.js diff --git a/x-pack/legacy/plugins/canvas/public/components/app/index.js b/x-pack/plugins/canvas/public/components/app/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/app/index.js rename to x-pack/plugins/canvas/public/components/app/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/app/track_route_change.js b/x-pack/plugins/canvas/public/components/app/track_route_change.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/app/track_route_change.js rename to x-pack/plugins/canvas/public/components/app/track_route_change.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add/arg_add.js b/x-pack/plugins/canvas/public/components/arg_add/arg_add.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add/arg_add.js rename to x-pack/plugins/canvas/public/components/arg_add/arg_add.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add/arg_add.scss b/x-pack/plugins/canvas/public/components/arg_add/arg_add.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add/arg_add.scss rename to x-pack/plugins/canvas/public/components/arg_add/arg_add.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add/index.js b/x-pack/plugins/canvas/public/components/arg_add/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add/index.js rename to x-pack/plugins/canvas/public/components/arg_add/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add_popover/arg_add_popover.scss b/x-pack/plugins/canvas/public/components/arg_add_popover/arg_add_popover.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add_popover/arg_add_popover.scss rename to x-pack/plugins/canvas/public/components/arg_add_popover/arg_add_popover.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add_popover/arg_add_popover.tsx b/x-pack/plugins/canvas/public/components/arg_add_popover/arg_add_popover.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add_popover/arg_add_popover.tsx rename to x-pack/plugins/canvas/public/components/arg_add_popover/arg_add_popover.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_add_popover/index.ts b/x-pack/plugins/canvas/public/components/arg_add_popover/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_add_popover/index.ts rename to x-pack/plugins/canvas/public/components/arg_add_popover/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/advanced_failure.js b/x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/advanced_failure.js rename to x-pack/plugins/canvas/public/components/arg_form/advanced_failure.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/arg_form.js b/x-pack/plugins/canvas/public/components/arg_form/arg_form.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/arg_form.js rename to x-pack/plugins/canvas/public/components/arg_form/arg_form.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/arg_form.scss b/x-pack/plugins/canvas/public/components/arg_form/arg_form.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/arg_form.scss rename to x-pack/plugins/canvas/public/components/arg_form/arg_form.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/arg_label.js b/x-pack/plugins/canvas/public/components/arg_form/arg_label.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/arg_label.js rename to x-pack/plugins/canvas/public/components/arg_form/arg_label.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/arg_simple_form.tsx b/x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/arg_simple_form.tsx rename to x-pack/plugins/canvas/public/components/arg_form/arg_simple_form.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/arg_template_form.js b/x-pack/plugins/canvas/public/components/arg_form/arg_template_form.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/arg_template_form.js rename to x-pack/plugins/canvas/public/components/arg_form/arg_template_form.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/index.js b/x-pack/plugins/canvas/public/components/arg_form/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/index.js rename to x-pack/plugins/canvas/public/components/arg_form/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/pending_arg_value.js b/x-pack/plugins/canvas/public/components/arg_form/pending_arg_value.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/pending_arg_value.js rename to x-pack/plugins/canvas/public/components/arg_form/pending_arg_value.js diff --git a/x-pack/legacy/plugins/canvas/public/components/arg_form/simple_failure.tsx b/x-pack/plugins/canvas/public/components/arg_form/simple_failure.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/arg_form/simple_failure.tsx rename to x-pack/plugins/canvas/public/components/arg_form/simple_failure.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot rename to x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.examples.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.examples.storyshot rename to x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot rename to x-pack/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset.examples.tsx b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/asset.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset.examples.tsx rename to x-pack/plugins/canvas/public/components/asset_manager/__examples__/asset.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx b/x-pack/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx rename to x-pack/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx b/x-pack/plugins/canvas/public/components/asset_manager/asset.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx rename to x-pack/plugins/canvas/public/components/asset_manager/asset.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss b/x-pack/plugins/canvas/public/components/asset_manager/asset_manager.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss rename to x-pack/plugins/canvas/public/components/asset_manager/asset_manager.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx b/x-pack/plugins/canvas/public/components/asset_manager/asset_manager.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx rename to x-pack/plugins/canvas/public/components/asset_manager/asset_manager.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx b/x-pack/plugins/canvas/public/components/asset_manager/asset_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx rename to x-pack/plugins/canvas/public/components/asset_manager/asset_modal.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/index.ts b/x-pack/plugins/canvas/public/components/asset_manager/index.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/index.ts rename to x-pack/plugins/canvas/public/components/asset_manager/index.ts index 3fd34d6d2a9bb..49894b9d87414 100644 --- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/index.ts +++ b/x-pack/plugins/canvas/public/components/asset_manager/index.ts @@ -21,7 +21,7 @@ import { getId } from '../../lib/get_id'; // @ts-ignore Untyped Local import { findExistingAsset } from '../../lib/find_existing_asset'; import { VALID_IMAGE_TYPES } from '../../../common/lib/constants'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { WithKibanaProps } from '../../'; import { AssetManager as Component, Props as AssetManagerProps } from './asset_manager'; diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_picker/asset_picker.scss b/x-pack/plugins/canvas/public/components/asset_picker/asset_picker.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_picker/asset_picker.scss rename to x-pack/plugins/canvas/public/components/asset_picker/asset_picker.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_picker/asset_picker.tsx b/x-pack/plugins/canvas/public/components/asset_picker/asset_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_picker/asset_picker.tsx rename to x-pack/plugins/canvas/public/components/asset_picker/asset_picker.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_picker/index.ts b/x-pack/plugins/canvas/public/components/asset_picker/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/asset_picker/index.ts rename to x-pack/plugins/canvas/public/components/asset_picker/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/autocomplete/autocomplete.js b/x-pack/plugins/canvas/public/components/autocomplete/autocomplete.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/autocomplete/autocomplete.js rename to x-pack/plugins/canvas/public/components/autocomplete/autocomplete.js diff --git a/x-pack/legacy/plugins/canvas/public/components/autocomplete/autocomplete.scss b/x-pack/plugins/canvas/public/components/autocomplete/autocomplete.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/autocomplete/autocomplete.scss rename to x-pack/plugins/canvas/public/components/autocomplete/autocomplete.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/autocomplete/index.js b/x-pack/plugins/canvas/public/components/autocomplete/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/autocomplete/index.js rename to x-pack/plugins/canvas/public/components/autocomplete/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/border_connection/border_connection.js b/x-pack/plugins/canvas/public/components/border_connection/border_connection.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_connection/border_connection.js rename to x-pack/plugins/canvas/public/components/border_connection/border_connection.js diff --git a/x-pack/legacy/plugins/canvas/public/components/border_connection/border_connection.scss b/x-pack/plugins/canvas/public/components/border_connection/border_connection.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_connection/border_connection.scss rename to x-pack/plugins/canvas/public/components/border_connection/border_connection.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/border_connection/index.js b/x-pack/plugins/canvas/public/components/border_connection/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_connection/index.js rename to x-pack/plugins/canvas/public/components/border_connection/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/border_resize_handle/border_resize_handle.js b/x-pack/plugins/canvas/public/components/border_resize_handle/border_resize_handle.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_resize_handle/border_resize_handle.js rename to x-pack/plugins/canvas/public/components/border_resize_handle/border_resize_handle.js diff --git a/x-pack/legacy/plugins/canvas/public/components/border_resize_handle/border_resize_handle.scss b/x-pack/plugins/canvas/public/components/border_resize_handle/border_resize_handle.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_resize_handle/border_resize_handle.scss rename to x-pack/plugins/canvas/public/components/border_resize_handle/border_resize_handle.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/border_resize_handle/index.js b/x-pack/plugins/canvas/public/components/border_resize_handle/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/border_resize_handle/index.js rename to x-pack/plugins/canvas/public/components/border_resize_handle/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/clipboard/clipboard.scss b/x-pack/plugins/canvas/public/components/clipboard/clipboard.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/clipboard/clipboard.scss rename to x-pack/plugins/canvas/public/components/clipboard/clipboard.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/clipboard/clipboard.tsx b/x-pack/plugins/canvas/public/components/clipboard/clipboard.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/clipboard/clipboard.tsx rename to x-pack/plugins/canvas/public/components/clipboard/clipboard.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/clipboard/index.ts b/x-pack/plugins/canvas/public/components/clipboard/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/clipboard/index.ts rename to x-pack/plugins/canvas/public/components/clipboard/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.stories.storyshot b/x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.stories.storyshot rename to x-pack/plugins/canvas/public/components/color_dot/__examples__/__snapshots__/color_dot.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/color_dot/__examples__/color_dot.stories.tsx b/x-pack/plugins/canvas/public/components/color_dot/__examples__/color_dot.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_dot/__examples__/color_dot.stories.tsx rename to x-pack/plugins/canvas/public/components/color_dot/__examples__/color_dot.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_dot/color_dot.scss b/x-pack/plugins/canvas/public/components/color_dot/color_dot.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_dot/color_dot.scss rename to x-pack/plugins/canvas/public/components/color_dot/color_dot.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/color_dot/color_dot.tsx b/x-pack/plugins/canvas/public/components/color_dot/color_dot.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_dot/color_dot.tsx rename to x-pack/plugins/canvas/public/components/color_dot/color_dot.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_dot/index.ts b/x-pack/plugins/canvas/public/components/color_dot/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_dot/index.ts rename to x-pack/plugins/canvas/public/components/color_dot/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.stories.storyshot b/x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.stories.storyshot rename to x-pack/plugins/canvas/public/components/color_manager/__examples__/__snapshots__/color_manager.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/color_manager/__examples__/color_manager.stories.tsx b/x-pack/plugins/canvas/public/components/color_manager/__examples__/color_manager.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_manager/__examples__/color_manager.stories.tsx rename to x-pack/plugins/canvas/public/components/color_manager/__examples__/color_manager.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_manager/color_manager.tsx b/x-pack/plugins/canvas/public/components/color_manager/color_manager.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_manager/color_manager.tsx rename to x-pack/plugins/canvas/public/components/color_manager/color_manager.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_manager/index.ts b/x-pack/plugins/canvas/public/components/color_manager/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_manager/index.ts rename to x-pack/plugins/canvas/public/components/color_manager/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.stories.storyshot b/x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.stories.storyshot rename to x-pack/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/color_palette.stories.tsx b/x-pack/plugins/canvas/public/components/color_palette/__examples__/color_palette.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/color_palette.stories.tsx rename to x-pack/plugins/canvas/public/components/color_palette/__examples__/color_palette.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/color_palette.scss b/x-pack/plugins/canvas/public/components/color_palette/color_palette.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_palette/color_palette.scss rename to x-pack/plugins/canvas/public/components/color_palette/color_palette.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/color_palette.tsx b/x-pack/plugins/canvas/public/components/color_palette/color_palette.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_palette/color_palette.tsx rename to x-pack/plugins/canvas/public/components/color_palette/color_palette.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/index.ts b/x-pack/plugins/canvas/public/components/color_palette/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_palette/index.ts rename to x-pack/plugins/canvas/public/components/color_palette/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.stories.storyshot b/x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.stories.storyshot rename to x-pack/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/color_picker.stories.tsx b/x-pack/plugins/canvas/public/components/color_picker/__examples__/color_picker.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/color_picker.stories.tsx rename to x-pack/plugins/canvas/public/components/color_picker/__examples__/color_picker.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker/color_picker.tsx b/x-pack/plugins/canvas/public/components/color_picker/color_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker/color_picker.tsx rename to x-pack/plugins/canvas/public/components/color_picker/color_picker.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker/index.ts b/x-pack/plugins/canvas/public/components/color_picker/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker/index.ts rename to x-pack/plugins/canvas/public/components/color_picker/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/__examples__/__snapshots__/color_picker_popover.stories.storyshot b/x-pack/plugins/canvas/public/components/color_picker_popover/__examples__/__snapshots__/color_picker_popover.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker_popover/__examples__/__snapshots__/color_picker_popover.stories.storyshot rename to x-pack/plugins/canvas/public/components/color_picker_popover/__examples__/__snapshots__/color_picker_popover.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/__examples__/color_picker_popover.stories.tsx b/x-pack/plugins/canvas/public/components/color_picker_popover/__examples__/color_picker_popover.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker_popover/__examples__/color_picker_popover.stories.tsx rename to x-pack/plugins/canvas/public/components/color_picker_popover/__examples__/color_picker_popover.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.scss b/x-pack/plugins/canvas/public/components/color_picker_popover/color_picker_popover.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.scss rename to x-pack/plugins/canvas/public/components/color_picker_popover/color_picker_popover.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx b/x-pack/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx rename to x-pack/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/index.ts b/x-pack/plugins/canvas/public/components/color_picker_popover/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/color_picker_popover/index.ts rename to x-pack/plugins/canvas/public/components/color_picker_popover/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/confirm_modal/confirm_modal.tsx b/x-pack/plugins/canvas/public/components/confirm_modal/confirm_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/confirm_modal/confirm_modal.tsx rename to x-pack/plugins/canvas/public/components/confirm_modal/confirm_modal.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/confirm_modal/index.ts b/x-pack/plugins/canvas/public/components/confirm_modal/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/confirm_modal/index.ts rename to x-pack/plugins/canvas/public/components/confirm_modal/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot b/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot rename to x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/custom_element_modal.examples.tsx b/x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/custom_element_modal.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/custom_element_modal.examples.tsx rename to x-pack/plugins/canvas/public/components/custom_element_modal/__examples__/custom_element_modal.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.scss b/x-pack/plugins/canvas/public/components/custom_element_modal/custom_element_modal.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.scss rename to x-pack/plugins/canvas/public/components/custom_element_modal/custom_element_modal.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx b/x-pack/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx rename to x-pack/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/index.tsx b/x-pack/plugins/canvas/public/components/custom_element_modal/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/custom_element_modal/index.tsx rename to x-pack/plugins/canvas/public/components/custom_element_modal/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.js b/x-pack/plugins/canvas/public/components/datasource/datasource.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource.js rename to x-pack/plugins/canvas/public/components/datasource/datasource.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss b/x-pack/plugins/canvas/public/components/datasource/datasource.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource.scss rename to x-pack/plugins/canvas/public/components/datasource/datasource.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js b/x-pack/plugins/canvas/public/components/datasource/datasource_component.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource_component.js rename to x-pack/plugins/canvas/public/components/datasource/datasource_component.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.js b/x-pack/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.js rename to x-pack/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.scss b/x-pack/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.scss rename to x-pack/plugins/canvas/public/components/datasource/datasource_preview/datasource_preview.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/index.js b/x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource_preview/index.js rename to x-pack/plugins/canvas/public/components/datasource/datasource_preview/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js b/x-pack/plugins/canvas/public/components/datasource/datasource_selector.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/datasource_selector.js rename to x-pack/plugins/canvas/public/components/datasource/datasource_selector.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/index.js b/x-pack/plugins/canvas/public/components/datasource/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/index.js rename to x-pack/plugins/canvas/public/components/datasource/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datasource/no_datasource.js b/x-pack/plugins/canvas/public/components/datasource/no_datasource.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datasource/no_datasource.js rename to x-pack/plugins/canvas/public/components/datasource/no_datasource.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datatable/datatable.js b/x-pack/plugins/canvas/public/components/datatable/datatable.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datatable/datatable.js rename to x-pack/plugins/canvas/public/components/datatable/datatable.js diff --git a/x-pack/legacy/plugins/canvas/public/components/datatable/datatable.scss b/x-pack/plugins/canvas/public/components/datatable/datatable.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datatable/datatable.scss rename to x-pack/plugins/canvas/public/components/datatable/datatable.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/datatable/index.js b/x-pack/plugins/canvas/public/components/datatable/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/datatable/index.js rename to x-pack/plugins/canvas/public/components/datatable/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/__snapshots__/debug.examples.storyshot b/x-pack/plugins/canvas/public/components/debug/__examples__/__snapshots__/debug.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/__examples__/__snapshots__/debug.examples.storyshot rename to x-pack/plugins/canvas/public/components/debug/__examples__/__snapshots__/debug.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx b/x-pack/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx rename to x-pack/plugins/canvas/public/components/debug/__examples__/debug.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/__examples__/helpers.tsx b/x-pack/plugins/canvas/public/components/debug/__examples__/helpers.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/__examples__/helpers.tsx rename to x-pack/plugins/canvas/public/components/debug/__examples__/helpers.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/debug.scss b/x-pack/plugins/canvas/public/components/debug/debug.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/debug.scss rename to x-pack/plugins/canvas/public/components/debug/debug.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/debug.tsx b/x-pack/plugins/canvas/public/components/debug/debug.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/debug.tsx rename to x-pack/plugins/canvas/public/components/debug/debug.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/debug/index.tsx b/x-pack/plugins/canvas/public/components/debug/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/debug/index.tsx rename to x-pack/plugins/canvas/public/components/debug/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/dom_preview/dom_preview.js b/x-pack/plugins/canvas/public/components/dom_preview/dom_preview.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dom_preview/dom_preview.js rename to x-pack/plugins/canvas/public/components/dom_preview/dom_preview.js diff --git a/x-pack/legacy/plugins/canvas/public/components/dom_preview/dom_preview.scss b/x-pack/plugins/canvas/public/components/dom_preview/dom_preview.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dom_preview/dom_preview.scss rename to x-pack/plugins/canvas/public/components/dom_preview/dom_preview.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/dom_preview/index.js b/x-pack/plugins/canvas/public/components/dom_preview/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dom_preview/index.js rename to x-pack/plugins/canvas/public/components/dom_preview/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/download/__tests__/download.test.tsx b/x-pack/plugins/canvas/public/components/download/__tests__/download.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/download/__tests__/download.test.tsx rename to x-pack/plugins/canvas/public/components/download/__tests__/download.test.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/download/download.tsx b/x-pack/plugins/canvas/public/components/download/download.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/download/download.tsx rename to x-pack/plugins/canvas/public/components/download/download.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/download/index.ts b/x-pack/plugins/canvas/public/components/download/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/download/index.ts rename to x-pack/plugins/canvas/public/components/download/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.js b/x-pack/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.js rename to x-pack/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.js diff --git a/x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.scss b/x-pack/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.scss rename to x-pack/plugins/canvas/public/components/dragbox_annotation/dragbox_annotation.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/index.js b/x-pack/plugins/canvas/public/components/dragbox_annotation/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/dragbox_annotation/index.js rename to x-pack/plugins/canvas/public/components/dragbox_annotation/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.stories.storyshot b/x-pack/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.stories.storyshot rename to x-pack/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_card.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_controls.examples.storyshot b/x-pack/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_controls.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_controls.examples.storyshot rename to x-pack/plugins/canvas/public/components/element_card/__examples__/__snapshots__/element_controls.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/element_card.stories.tsx b/x-pack/plugins/canvas/public/components/element_card/__examples__/element_card.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/__examples__/element_card.stories.tsx rename to x-pack/plugins/canvas/public/components/element_card/__examples__/element_card.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/element_card.scss b/x-pack/plugins/canvas/public/components/element_card/element_card.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/element_card.scss rename to x-pack/plugins/canvas/public/components/element_card/element_card.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/element_card.tsx b/x-pack/plugins/canvas/public/components/element_card/element_card.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/element_card.tsx rename to x-pack/plugins/canvas/public/components/element_card/element_card.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/element_card/index.tsx b/x-pack/plugins/canvas/public/components/element_card/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_card/index.tsx rename to x-pack/plugins/canvas/public/components/element_card/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/element_config/element_config.js b/x-pack/plugins/canvas/public/components/element_config/element_config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_config/element_config.js rename to x-pack/plugins/canvas/public/components/element_config/element_config.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_config/index.js b/x-pack/plugins/canvas/public/components/element_config/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_config/index.js rename to x-pack/plugins/canvas/public/components/element_config/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_content/element_content.js b/x-pack/plugins/canvas/public/components/element_content/element_content.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_content/element_content.js rename to x-pack/plugins/canvas/public/components/element_content/element_content.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_content/element_content.scss b/x-pack/plugins/canvas/public/components/element_content/element_content.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_content/element_content.scss rename to x-pack/plugins/canvas/public/components/element_content/element_content.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/element_content/index.js b/x-pack/plugins/canvas/public/components/element_content/index.js similarity index 92% rename from x-pack/legacy/plugins/canvas/public/components/element_content/index.js rename to x-pack/plugins/canvas/public/components/element_content/index.js index df411b6d11f1c..3d7cca95e10b7 100644 --- a/x-pack/legacy/plugins/canvas/public/components/element_content/index.js +++ b/x-pack/plugins/canvas/public/components/element_content/index.js @@ -9,7 +9,7 @@ import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; import { get } from 'lodash'; import { getSelectedPage, getPageById } from '../../state/selectors/workpad'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { ElementContent as Component } from './element_content'; const mapStateToProps = state => ({ diff --git a/x-pack/legacy/plugins/canvas/public/components/element_content/invalid_element_type.js b/x-pack/plugins/canvas/public/components/element_content/invalid_element_type.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_content/invalid_element_type.js rename to x-pack/plugins/canvas/public/components/element_content/invalid_element_type.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_content/invalid_expression.js b/x-pack/plugins/canvas/public/components/element_content/invalid_expression.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_content/invalid_expression.js rename to x-pack/plugins/canvas/public/components/element_content/invalid_expression.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js b/x-pack/plugins/canvas/public/components/element_share_container/element_share_container.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_share_container/element_share_container.js rename to x-pack/plugins/canvas/public/components/element_share_container/element_share_container.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_share_container/index.js b/x-pack/plugins/canvas/public/components/element_share_container/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_share_container/index.js rename to x-pack/plugins/canvas/public/components/element_share_container/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_wrapper/element_wrapper.js b/x-pack/plugins/canvas/public/components/element_wrapper/element_wrapper.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_wrapper/element_wrapper.js rename to x-pack/plugins/canvas/public/components/element_wrapper/element_wrapper.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_wrapper/index.js b/x-pack/plugins/canvas/public/components/element_wrapper/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_wrapper/index.js rename to x-pack/plugins/canvas/public/components/element_wrapper/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/element_wrapper/lib/handlers.js b/x-pack/plugins/canvas/public/components/element_wrapper/lib/handlers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/element_wrapper/lib/handlers.js rename to x-pack/plugins/canvas/public/components/element_wrapper/lib/handlers.js diff --git a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx b/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.tsx similarity index 95% rename from x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx rename to x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.tsx index 4916a27fcbe60..35eedde59a014 100644 --- a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/flyout.tsx +++ b/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.tsx @@ -9,9 +9,9 @@ import { EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody, EuiTitle } from '@elastic/eu import { SavedObjectFinderUi, SavedObjectMetaData, -} from '../../../../../../../src/plugins/saved_objects/public/'; +} from '../../../../../../src/plugins/saved_objects/public/'; import { ComponentStrings } from '../../../i18n'; -import { CoreStart } from '../../../../../../../src/core/public'; +import { CoreStart } from '../../../../../../src/core/public'; import { CanvasStartDeps } from '../../plugin'; const { AddEmbeddableFlyout: strings } = ComponentStrings; diff --git a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx b/x-pack/plugins/canvas/public/components/embeddable_flyout/index.tsx similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx rename to x-pack/plugins/canvas/public/components/embeddable_flyout/index.tsx index c13cbfd042237..8e69396f67c2e 100644 --- a/x-pack/legacy/plugins/canvas/public/components/embeddable_flyout/index.tsx +++ b/x-pack/plugins/canvas/public/components/embeddable_flyout/index.tsx @@ -15,7 +15,7 @@ import { addElement } from '../../state/actions/elements'; import { getSelectedPage } from '../../state/selectors/workpad'; import { EmbeddableTypes } from '../../../canvas_plugin_src/expression_types/embeddable'; import { WithKibanaProps } from '../../index'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; const allowedEmbeddables = { [EmbeddableTypes.map]: (id: string) => { diff --git a/x-pack/legacy/plugins/canvas/public/components/enhance/error_boundary.tsx b/x-pack/plugins/canvas/public/components/enhance/error_boundary.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/enhance/error_boundary.tsx rename to x-pack/plugins/canvas/public/components/enhance/error_boundary.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/enhance/stateful_prop.js b/x-pack/plugins/canvas/public/components/enhance/stateful_prop.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/enhance/stateful_prop.js rename to x-pack/plugins/canvas/public/components/enhance/stateful_prop.js diff --git a/x-pack/legacy/plugins/canvas/public/components/error/error.js b/x-pack/plugins/canvas/public/components/error/error.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/error/error.js rename to x-pack/plugins/canvas/public/components/error/error.js diff --git a/x-pack/legacy/plugins/canvas/public/components/error/index.js b/x-pack/plugins/canvas/public/components/error/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/error/index.js rename to x-pack/plugins/canvas/public/components/error/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/error/show_debugging.js b/x-pack/plugins/canvas/public/components/error/show_debugging.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/error/show_debugging.js rename to x-pack/plugins/canvas/public/components/error/show_debugging.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_field_select/es_field_select.js b/x-pack/plugins/canvas/public/components/es_field_select/es_field_select.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_field_select/es_field_select.js rename to x-pack/plugins/canvas/public/components/es_field_select/es_field_select.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_field_select/index.js b/x-pack/plugins/canvas/public/components/es_field_select/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_field_select/index.js rename to x-pack/plugins/canvas/public/components/es_field_select/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_fields_select/es_fields_select.js b/x-pack/plugins/canvas/public/components/es_fields_select/es_fields_select.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_fields_select/es_fields_select.js rename to x-pack/plugins/canvas/public/components/es_fields_select/es_fields_select.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_fields_select/index.js b/x-pack/plugins/canvas/public/components/es_fields_select/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_fields_select/index.js rename to x-pack/plugins/canvas/public/components/es_fields_select/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_index_select/es_index_select.js b/x-pack/plugins/canvas/public/components/es_index_select/es_index_select.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_index_select/es_index_select.js rename to x-pack/plugins/canvas/public/components/es_index_select/es_index_select.js diff --git a/x-pack/legacy/plugins/canvas/public/components/es_index_select/index.js b/x-pack/plugins/canvas/public/components/es_index_select/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/es_index_select/index.js rename to x-pack/plugins/canvas/public/components/es_index_select/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/expression/element_not_selected.js b/x-pack/plugins/canvas/public/components/expression/element_not_selected.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression/element_not_selected.js rename to x-pack/plugins/canvas/public/components/expression/element_not_selected.js diff --git a/x-pack/legacy/plugins/canvas/public/components/expression/expression.js b/x-pack/plugins/canvas/public/components/expression/expression.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression/expression.js rename to x-pack/plugins/canvas/public/components/expression/expression.js diff --git a/x-pack/legacy/plugins/canvas/public/components/expression/expression.scss b/x-pack/plugins/canvas/public/components/expression/expression.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression/expression.scss rename to x-pack/plugins/canvas/public/components/expression/expression.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/expression/index.js b/x-pack/plugins/canvas/public/components/expression/index.js similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/expression/index.js rename to x-pack/plugins/canvas/public/components/expression/index.js index 29d22c0e1804a..c2b559fe03230 100644 --- a/x-pack/legacy/plugins/canvas/public/components/expression/index.js +++ b/x-pack/plugins/canvas/public/components/expression/index.js @@ -15,7 +15,7 @@ import { renderComponent, } from 'recompose'; import { fromExpression } from '@kbn/interpreter/common'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { getSelectedPage, getSelectedElement } from '../../state/selectors/workpad'; import { setExpression, flushContext } from '../../state/actions/elements'; import { ElementNotSelected } from './element_not_selected'; diff --git a/x-pack/legacy/plugins/canvas/public/components/expression_input/__examples__/__snapshots__/expression_input.examples.storyshot b/x-pack/plugins/canvas/public/components/expression_input/__examples__/__snapshots__/expression_input.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression_input/__examples__/__snapshots__/expression_input.examples.storyshot rename to x-pack/plugins/canvas/public/components/expression_input/__examples__/__snapshots__/expression_input.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx b/x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx rename to x-pack/plugins/canvas/public/components/expression_input/__examples__/expression_input.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/expression_input/expression_input.tsx b/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx similarity index 98% rename from x-pack/legacy/plugins/canvas/public/components/expression_input/expression_input.tsx rename to x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx index faac2ae883c13..99e12b14104be 100644 --- a/x-pack/legacy/plugins/canvas/public/components/expression_input/expression_input.tsx +++ b/x-pack/plugins/canvas/public/components/expression_input/expression_input.tsx @@ -9,8 +9,8 @@ import PropTypes from 'prop-types'; import { EuiFormRow } from '@elastic/eui'; import { debounce } from 'lodash'; import { monaco } from '@kbn/ui-shared-deps/monaco'; -import { ExpressionFunction } from '../../../../../../../src/plugins/expressions'; -import { CodeEditor } from '../../../../../../../src/plugins/kibana_react/public'; +import { ExpressionFunction } from '../../../types'; +import { CodeEditor } from '../../../../../../src/plugins/kibana_react/public'; import { AutocompleteSuggestion, getAutocompleteSuggestions, diff --git a/x-pack/legacy/plugins/canvas/public/components/expression_input/index.js b/x-pack/plugins/canvas/public/components/expression_input/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/expression_input/index.js rename to x-pack/plugins/canvas/public/components/expression_input/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/expression_input/reference.ts b/x-pack/plugins/canvas/public/components/expression_input/reference.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/expression_input/reference.ts rename to x-pack/plugins/canvas/public/components/expression_input/reference.ts index ca3819195fcbd..a24dacf066475 100644 --- a/x-pack/legacy/plugins/canvas/public/components/expression_input/reference.ts +++ b/x-pack/plugins/canvas/public/components/expression_input/reference.ts @@ -8,7 +8,7 @@ import { ComponentStrings } from '../../../i18n'; import { ExpressionFunction, ExpressionFunctionParameter, -} from '../../../../../../../src/plugins/expressions'; +} from '../../../../../../src/plugins/expressions'; const { ExpressionInput: strings } = ComponentStrings; diff --git a/x-pack/legacy/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.stories.storyshot b/x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.stories.storyshot rename to x-pack/plugins/canvas/public/components/file_upload/__snapshots__/file_upload.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/file_upload/file_upload.stories.tsx b/x-pack/plugins/canvas/public/components/file_upload/file_upload.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/file_upload/file_upload.stories.tsx rename to x-pack/plugins/canvas/public/components/file_upload/file_upload.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/file_upload/file_upload.tsx b/x-pack/plugins/canvas/public/components/file_upload/file_upload.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/file_upload/file_upload.tsx rename to x-pack/plugins/canvas/public/components/file_upload/file_upload.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.stories.storyshot b/x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.stories.storyshot rename to x-pack/plugins/canvas/public/components/font_picker/__snapshots__/font_picker.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/font_picker/font_picker.stories.tsx b/x-pack/plugins/canvas/public/components/font_picker/font_picker.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/font_picker/font_picker.stories.tsx rename to x-pack/plugins/canvas/public/components/font_picker/font_picker.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/font_picker/font_picker.tsx b/x-pack/plugins/canvas/public/components/font_picker/font_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/font_picker/font_picker.tsx rename to x-pack/plugins/canvas/public/components/font_picker/font_picker.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/font_picker/index.js b/x-pack/plugins/canvas/public/components/font_picker/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/font_picker/index.js rename to x-pack/plugins/canvas/public/components/font_picker/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/format_select/format_select.tsx b/x-pack/plugins/canvas/public/components/format_select/format_select.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/format_select/format_select.tsx rename to x-pack/plugins/canvas/public/components/format_select/format_select.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/format_select/index.ts b/x-pack/plugins/canvas/public/components/format_select/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/format_select/index.ts rename to x-pack/plugins/canvas/public/components/format_select/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/fullscreen/fullscreen.js b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/fullscreen/fullscreen.js rename to x-pack/plugins/canvas/public/components/fullscreen/fullscreen.js diff --git a/x-pack/legacy/plugins/canvas/public/components/fullscreen/fullscreen.scss b/x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/fullscreen/fullscreen.scss rename to x-pack/plugins/canvas/public/components/fullscreen/fullscreen.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/fullscreen/index.js b/x-pack/plugins/canvas/public/components/fullscreen/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/fullscreen/index.js rename to x-pack/plugins/canvas/public/components/fullscreen/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_form.js b/x-pack/plugins/canvas/public/components/function_form/function_form.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_form.js rename to x-pack/plugins/canvas/public/components/function_form/function_form.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_form.scss b/x-pack/plugins/canvas/public/components/function_form/function_form.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_form.scss rename to x-pack/plugins/canvas/public/components/function_form/function_form.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_form_component.js b/x-pack/plugins/canvas/public/components/function_form/function_form_component.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_form_component.js rename to x-pack/plugins/canvas/public/components/function_form/function_form_component.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_form_context_error.tsx b/x-pack/plugins/canvas/public/components/function_form/function_form_context_error.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_form_context_error.tsx rename to x-pack/plugins/canvas/public/components/function_form/function_form_context_error.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_form_context_pending.js b/x-pack/plugins/canvas/public/components/function_form/function_form_context_pending.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_form_context_pending.js rename to x-pack/plugins/canvas/public/components/function_form/function_form_context_pending.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/function_unknown.tsx b/x-pack/plugins/canvas/public/components/function_form/function_unknown.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/function_unknown.tsx rename to x-pack/plugins/canvas/public/components/function_form/function_unknown.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form/index.js b/x-pack/plugins/canvas/public/components/function_form/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form/index.js rename to x-pack/plugins/canvas/public/components/function_form/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form_list/function_form_list.js b/x-pack/plugins/canvas/public/components/function_form_list/function_form_list.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form_list/function_form_list.js rename to x-pack/plugins/canvas/public/components/function_form_list/function_form_list.js diff --git a/x-pack/legacy/plugins/canvas/public/components/function_form_list/index.js b/x-pack/plugins/canvas/public/components/function_form_list/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/function_form_list/index.js rename to x-pack/plugins/canvas/public/components/function_form_list/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js b/x-pack/plugins/canvas/public/components/help_menu/help_menu.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/help_menu/help_menu.js rename to x-pack/plugins/canvas/public/components/help_menu/help_menu.js diff --git a/x-pack/legacy/plugins/canvas/public/components/help_menu/index.js b/x-pack/plugins/canvas/public/components/help_menu/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/help_menu/index.js rename to x-pack/plugins/canvas/public/components/help_menu/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/hover_annotation/hover_annotation.js b/x-pack/plugins/canvas/public/components/hover_annotation/hover_annotation.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/hover_annotation/hover_annotation.js rename to x-pack/plugins/canvas/public/components/hover_annotation/hover_annotation.js diff --git a/x-pack/legacy/plugins/canvas/public/components/hover_annotation/hover_annotation.scss b/x-pack/plugins/canvas/public/components/hover_annotation/hover_annotation.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/hover_annotation/hover_annotation.scss rename to x-pack/plugins/canvas/public/components/hover_annotation/hover_annotation.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/hover_annotation/index.js b/x-pack/plugins/canvas/public/components/hover_annotation/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/hover_annotation/index.js rename to x-pack/plugins/canvas/public/components/hover_annotation/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.stories.storyshot b/x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.stories.storyshot rename to x-pack/plugins/canvas/public/components/item_grid/__examples__/__snapshots__/item_grid.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/item_grid/__examples__/item_grid.stories.tsx b/x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/item_grid/__examples__/item_grid.stories.tsx rename to x-pack/plugins/canvas/public/components/item_grid/__examples__/item_grid.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/item_grid/index.ts b/x-pack/plugins/canvas/public/components/item_grid/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/item_grid/index.ts rename to x-pack/plugins/canvas/public/components/item_grid/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/item_grid/item_grid.tsx b/x-pack/plugins/canvas/public/components/item_grid/item_grid.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/item_grid/item_grid.tsx rename to x-pack/plugins/canvas/public/components/item_grid/item_grid.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.stories.storyshot b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.stories.storyshot rename to x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/__snapshots__/keyboard_shortcuts_doc.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/keyboard_shortcuts_doc.stories.tsx b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/keyboard_shortcuts_doc.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/keyboard_shortcuts_doc.stories.tsx rename to x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/__examples__/keyboard_shortcuts_doc.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/index.ts b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/index.ts rename to x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/keyboard_shortcuts_doc.tsx b/x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/keyboard_shortcuts_doc.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/keyboard_shortcuts_doc/keyboard_shortcuts_doc.tsx rename to x-pack/plugins/canvas/public/components/keyboard_shortcuts_doc/keyboard_shortcuts_doc.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/link/index.js b/x-pack/plugins/canvas/public/components/link/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/link/index.js rename to x-pack/plugins/canvas/public/components/link/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/link/link.js b/x-pack/plugins/canvas/public/components/link/link.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/link/link.js rename to x-pack/plugins/canvas/public/components/link/link.js diff --git a/x-pack/legacy/plugins/canvas/public/components/loading/__tests__/loading.js b/x-pack/plugins/canvas/public/components/loading/__tests__/loading.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/loading/__tests__/loading.js rename to x-pack/plugins/canvas/public/components/loading/__tests__/loading.js diff --git a/x-pack/legacy/plugins/canvas/public/components/loading/index.ts b/x-pack/plugins/canvas/public/components/loading/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/loading/index.ts rename to x-pack/plugins/canvas/public/components/loading/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/loading/loading.scss b/x-pack/plugins/canvas/public/components/loading/loading.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/loading/loading.scss rename to x-pack/plugins/canvas/public/components/loading/loading.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/loading/loading.tsx b/x-pack/plugins/canvas/public/components/loading/loading.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/loading/loading.tsx rename to x-pack/plugins/canvas/public/components/loading/loading.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/navbar/index.js b/x-pack/plugins/canvas/public/components/navbar/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/navbar/index.js rename to x-pack/plugins/canvas/public/components/navbar/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/navbar/navbar.js b/x-pack/plugins/canvas/public/components/navbar/navbar.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/navbar/navbar.js rename to x-pack/plugins/canvas/public/components/navbar/navbar.js diff --git a/x-pack/legacy/plugins/canvas/public/components/navbar/navbar.scss b/x-pack/plugins/canvas/public/components/navbar/navbar.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/navbar/navbar.scss rename to x-pack/plugins/canvas/public/components/navbar/navbar.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/page_config/index.js b/x-pack/plugins/canvas/public/components/page_config/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_config/index.js rename to x-pack/plugins/canvas/public/components/page_config/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_config/page_config.js b/x-pack/plugins/canvas/public/components/page_config/page_config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_config/page_config.js rename to x-pack/plugins/canvas/public/components/page_config/page_config.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_manager/index.js b/x-pack/plugins/canvas/public/components/page_manager/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_manager/index.js rename to x-pack/plugins/canvas/public/components/page_manager/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_manager/page_manager.js b/x-pack/plugins/canvas/public/components/page_manager/page_manager.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_manager/page_manager.js rename to x-pack/plugins/canvas/public/components/page_manager/page_manager.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_manager/page_manager.scss b/x-pack/plugins/canvas/public/components/page_manager/page_manager.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_manager/page_manager.scss rename to x-pack/plugins/canvas/public/components/page_manager/page_manager.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/page_preview/index.js b/x-pack/plugins/canvas/public/components/page_preview/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_preview/index.js rename to x-pack/plugins/canvas/public/components/page_preview/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_preview/page_controls.js b/x-pack/plugins/canvas/public/components/page_preview/page_controls.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_preview/page_controls.js rename to x-pack/plugins/canvas/public/components/page_preview/page_controls.js diff --git a/x-pack/legacy/plugins/canvas/public/components/page_preview/page_preview.js b/x-pack/plugins/canvas/public/components/page_preview/page_preview.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/page_preview/page_preview.js rename to x-pack/plugins/canvas/public/components/page_preview/page_preview.js diff --git a/x-pack/legacy/plugins/canvas/public/components/paginate/index.js b/x-pack/plugins/canvas/public/components/paginate/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/paginate/index.js rename to x-pack/plugins/canvas/public/components/paginate/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/paginate/paginate.js b/x-pack/plugins/canvas/public/components/paginate/paginate.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/paginate/paginate.js rename to x-pack/plugins/canvas/public/components/paginate/paginate.js diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_picker/index.js b/x-pack/plugins/canvas/public/components/palette_picker/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_picker/index.js rename to x-pack/plugins/canvas/public/components/palette_picker/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js b/x-pack/plugins/canvas/public/components/palette_picker/palette_picker.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js rename to x-pack/plugins/canvas/public/components/palette_picker/palette_picker.js diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.scss b/x-pack/plugins/canvas/public/components/palette_picker/palette_picker.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.scss rename to x-pack/plugins/canvas/public/components/palette_picker/palette_picker.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_swatch/index.js b/x-pack/plugins/canvas/public/components/palette_swatch/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_swatch/index.js rename to x-pack/plugins/canvas/public/components/palette_swatch/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_swatch/palette_swatch.js b/x-pack/plugins/canvas/public/components/palette_swatch/palette_swatch.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_swatch/palette_swatch.js rename to x-pack/plugins/canvas/public/components/palette_swatch/palette_swatch.js diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_swatch/palette_swatch.scss b/x-pack/plugins/canvas/public/components/palette_swatch/palette_swatch.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/palette_swatch/palette_swatch.scss rename to x-pack/plugins/canvas/public/components/palette_swatch/palette_swatch.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/popover/index.ts b/x-pack/plugins/canvas/public/components/popover/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/popover/index.ts rename to x-pack/plugins/canvas/public/components/popover/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx b/x-pack/plugins/canvas/public/components/popover/popover.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx rename to x-pack/plugins/canvas/public/components/popover/popover.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/positionable/index.js b/x-pack/plugins/canvas/public/components/positionable/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/positionable/index.js rename to x-pack/plugins/canvas/public/components/positionable/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/positionable/positionable.js b/x-pack/plugins/canvas/public/components/positionable/positionable.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/positionable/positionable.js rename to x-pack/plugins/canvas/public/components/positionable/positionable.js diff --git a/x-pack/legacy/plugins/canvas/public/components/positionable/positionable.scss b/x-pack/plugins/canvas/public/components/positionable/positionable.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/positionable/positionable.scss rename to x-pack/plugins/canvas/public/components/positionable/positionable.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/render_to_dom/index.js b/x-pack/plugins/canvas/public/components/render_to_dom/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/render_to_dom/index.js rename to x-pack/plugins/canvas/public/components/render_to_dom/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/render_to_dom/render_to_dom.js b/x-pack/plugins/canvas/public/components/render_to_dom/render_to_dom.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/render_to_dom/render_to_dom.js rename to x-pack/plugins/canvas/public/components/render_to_dom/render_to_dom.js diff --git a/x-pack/legacy/plugins/canvas/public/components/render_with_fn/index.js b/x-pack/plugins/canvas/public/components/render_with_fn/index.js similarity index 92% rename from x-pack/legacy/plugins/canvas/public/components/render_with_fn/index.js rename to x-pack/plugins/canvas/public/components/render_with_fn/index.js index cc234d2287c0c..473aaaf9d1ac6 100644 --- a/x-pack/legacy/plugins/canvas/public/components/render_with_fn/index.js +++ b/x-pack/plugins/canvas/public/components/render_with_fn/index.js @@ -7,7 +7,7 @@ import { compose, withProps, withPropsOnChange } from 'recompose'; import PropTypes from 'prop-types'; import isEqual from 'react-fast-compare'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { RenderWithFn as Component } from './render_with_fn'; import { ElementHandlers } from './lib/handlers'; diff --git a/x-pack/legacy/plugins/canvas/public/components/render_with_fn/lib/handlers.js b/x-pack/plugins/canvas/public/components/render_with_fn/lib/handlers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/render_with_fn/lib/handlers.js rename to x-pack/plugins/canvas/public/components/render_with_fn/lib/handlers.js diff --git a/x-pack/legacy/plugins/canvas/public/components/render_with_fn/render_with_fn.js b/x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/render_with_fn/render_with_fn.js rename to x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.js diff --git a/x-pack/legacy/plugins/canvas/public/components/rotation_handle/index.js b/x-pack/plugins/canvas/public/components/rotation_handle/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/rotation_handle/index.js rename to x-pack/plugins/canvas/public/components/rotation_handle/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/rotation_handle/rotation_handle.js b/x-pack/plugins/canvas/public/components/rotation_handle/rotation_handle.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/rotation_handle/rotation_handle.js rename to x-pack/plugins/canvas/public/components/rotation_handle/rotation_handle.js diff --git a/x-pack/legacy/plugins/canvas/public/components/rotation_handle/rotation_handle.scss b/x-pack/plugins/canvas/public/components/rotation_handle/rotation_handle.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/rotation_handle/rotation_handle.scss rename to x-pack/plugins/canvas/public/components/rotation_handle/rotation_handle.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/router/canvas_loading.js b/x-pack/plugins/canvas/public/components/router/canvas_loading.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/router/canvas_loading.js rename to x-pack/plugins/canvas/public/components/router/canvas_loading.js diff --git a/x-pack/legacy/plugins/canvas/public/components/router/index.ts b/x-pack/plugins/canvas/public/components/router/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/router/index.ts rename to x-pack/plugins/canvas/public/components/router/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/router/router.js b/x-pack/plugins/canvas/public/components/router/router.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/router/router.js rename to x-pack/plugins/canvas/public/components/router/router.js diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_grid.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_grid.stories.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/element_grid.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_grid.stories.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/element_grid.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts b/x-pack/plugins/canvas/public/components/saved_elements_modal/index.ts similarity index 98% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts rename to x-pack/plugins/canvas/public/components/saved_elements_modal/index.ts index 60d1d7462daa9..f14fc92e028db 100644 --- a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/index.ts @@ -11,7 +11,7 @@ import { camelCase } from 'lodash'; // @ts-ignore Untyped local import { cloneSubgraphs } from '../../lib/clone_subgraphs'; import * as customElementService from '../../lib/custom_element_service'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { WithKibanaProps } from '../../'; // @ts-ignore Untyped local import { selectToplevelNodes } from '../../state/actions/transient'; diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx rename to x-pack/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker/__examples__/__snapshots__/shape_picker.stories.storyshot b/x-pack/plugins/canvas/public/components/shape_picker/__examples__/__snapshots__/shape_picker.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker/__examples__/__snapshots__/shape_picker.stories.storyshot rename to x-pack/plugins/canvas/public/components/shape_picker/__examples__/__snapshots__/shape_picker.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker/__examples__/shape_picker.stories.tsx b/x-pack/plugins/canvas/public/components/shape_picker/__examples__/shape_picker.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker/__examples__/shape_picker.stories.tsx rename to x-pack/plugins/canvas/public/components/shape_picker/__examples__/shape_picker.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker/index.ts b/x-pack/plugins/canvas/public/components/shape_picker/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker/index.ts rename to x-pack/plugins/canvas/public/components/shape_picker/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker/shape_picker.scss b/x-pack/plugins/canvas/public/components/shape_picker/shape_picker.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker/shape_picker.scss rename to x-pack/plugins/canvas/public/components/shape_picker/shape_picker.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker/shape_picker.tsx b/x-pack/plugins/canvas/public/components/shape_picker/shape_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker/shape_picker.tsx rename to x-pack/plugins/canvas/public/components/shape_picker/shape_picker.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/__examples__/__snapshots__/shape_picker_popover.stories.storyshot b/x-pack/plugins/canvas/public/components/shape_picker_popover/__examples__/__snapshots__/shape_picker_popover.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/__examples__/__snapshots__/shape_picker_popover.stories.storyshot rename to x-pack/plugins/canvas/public/components/shape_picker_popover/__examples__/__snapshots__/shape_picker_popover.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/__examples__/shape_picker_popover.stories.tsx b/x-pack/plugins/canvas/public/components/shape_picker_popover/__examples__/shape_picker_popover.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/__examples__/shape_picker_popover.stories.tsx rename to x-pack/plugins/canvas/public/components/shape_picker_popover/__examples__/shape_picker_popover.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/index.tsx b/x-pack/plugins/canvas/public/components/shape_picker_popover/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/index.tsx rename to x-pack/plugins/canvas/public/components/shape_picker_popover/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx b/x-pack/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx rename to x-pack/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_preview/__examples__/__snapshots__/shape_preview.stories.storyshot b/x-pack/plugins/canvas/public/components/shape_preview/__examples__/__snapshots__/shape_preview.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_preview/__examples__/__snapshots__/shape_preview.stories.storyshot rename to x-pack/plugins/canvas/public/components/shape_preview/__examples__/__snapshots__/shape_preview.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_preview/__examples__/shape_preview.stories.tsx b/x-pack/plugins/canvas/public/components/shape_preview/__examples__/shape_preview.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_preview/__examples__/shape_preview.stories.tsx rename to x-pack/plugins/canvas/public/components/shape_preview/__examples__/shape_preview.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_preview/index.ts b/x-pack/plugins/canvas/public/components/shape_preview/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_preview/index.ts rename to x-pack/plugins/canvas/public/components/shape_preview/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_preview/shape_preview.scss b/x-pack/plugins/canvas/public/components/shape_preview/shape_preview.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_preview/shape_preview.scss rename to x-pack/plugins/canvas/public/components/shape_preview/shape_preview.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_preview/shape_preview.tsx b/x-pack/plugins/canvas/public/components/shape_preview/shape_preview.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/shape_preview/shape_preview.tsx rename to x-pack/plugins/canvas/public/components/shape_preview/shape_preview.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/group_settings.stories.storyshot b/x-pack/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/group_settings.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/group_settings.stories.storyshot rename to x-pack/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/group_settings.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/multi_element_settings.stories.storyshot b/x-pack/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/multi_element_settings.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/multi_element_settings.stories.storyshot rename to x-pack/plugins/canvas/public/components/sidebar/__examples__/__snapshots__/multi_element_settings.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/group_settings.stories.tsx b/x-pack/plugins/canvas/public/components/sidebar/__examples__/group_settings.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/group_settings.stories.tsx rename to x-pack/plugins/canvas/public/components/sidebar/__examples__/group_settings.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/multi_element_settings.stories.tsx b/x-pack/plugins/canvas/public/components/sidebar/__examples__/multi_element_settings.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/__examples__/multi_element_settings.stories.tsx rename to x-pack/plugins/canvas/public/components/sidebar/__examples__/multi_element_settings.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/element_settings.tsx b/x-pack/plugins/canvas/public/components/sidebar/element_settings/element_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/element_settings.tsx rename to x-pack/plugins/canvas/public/components/sidebar/element_settings/element_settings.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx b/x-pack/plugins/canvas/public/components/sidebar/element_settings/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/element_settings/index.tsx rename to x-pack/plugins/canvas/public/components/sidebar/element_settings/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/global_config.tsx b/x-pack/plugins/canvas/public/components/sidebar/global_config.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/global_config.tsx rename to x-pack/plugins/canvas/public/components/sidebar/global_config.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/group_settings.tsx b/x-pack/plugins/canvas/public/components/sidebar/group_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/group_settings.tsx rename to x-pack/plugins/canvas/public/components/sidebar/group_settings.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/index.tsx b/x-pack/plugins/canvas/public/components/sidebar/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/index.tsx rename to x-pack/plugins/canvas/public/components/sidebar/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/multi_element_settings.tsx b/x-pack/plugins/canvas/public/components/sidebar/multi_element_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/multi_element_settings.tsx rename to x-pack/plugins/canvas/public/components/sidebar/multi_element_settings.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar.scss b/x-pack/plugins/canvas/public/components/sidebar/sidebar.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar.scss rename to x-pack/plugins/canvas/public/components/sidebar/sidebar.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar.tsx b/x-pack/plugins/canvas/public/components/sidebar/sidebar.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar.tsx rename to x-pack/plugins/canvas/public/components/sidebar/sidebar.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_content.js b/x-pack/plugins/canvas/public/components/sidebar/sidebar_content.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_content.js rename to x-pack/plugins/canvas/public/components/sidebar/sidebar_content.js diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_section.js b/x-pack/plugins/canvas/public/components/sidebar/sidebar_section.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_section.js rename to x-pack/plugins/canvas/public/components/sidebar/sidebar_section.js diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_section_title.js b/x-pack/plugins/canvas/public/components/sidebar/sidebar_section_title.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar/sidebar_section_title.js rename to x-pack/plugins/canvas/public/components/sidebar/sidebar_section_title.js diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot b/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot rename to x-pack/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/sidebar_header.stories.tsx b/x-pack/plugins/canvas/public/components/sidebar_header/__examples__/sidebar_header.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/sidebar_header.stories.tsx rename to x-pack/plugins/canvas/public/components/sidebar_header/__examples__/sidebar_header.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/index.js b/x-pack/plugins/canvas/public/components/sidebar_header/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar_header/index.js rename to x-pack/plugins/canvas/public/components/sidebar_header/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/sidebar_header.scss b/x-pack/plugins/canvas/public/components/sidebar_header/sidebar_header.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar_header/sidebar_header.scss rename to x-pack/plugins/canvas/public/components/sidebar_header/sidebar_header.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/sidebar_header.tsx b/x-pack/plugins/canvas/public/components/sidebar_header/sidebar_header.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/sidebar_header/sidebar_header.tsx rename to x-pack/plugins/canvas/public/components/sidebar_header/sidebar_header.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.stories.storyshot b/x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.stories.storyshot rename to x-pack/plugins/canvas/public/components/tag/__examples__/__snapshots__/tag.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/tag/__examples__/tag.stories.tsx b/x-pack/plugins/canvas/public/components/tag/__examples__/tag.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag/__examples__/tag.stories.tsx rename to x-pack/plugins/canvas/public/components/tag/__examples__/tag.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag/index.tsx b/x-pack/plugins/canvas/public/components/tag/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag/index.tsx rename to x-pack/plugins/canvas/public/components/tag/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag/tag.tsx b/x-pack/plugins/canvas/public/components/tag/tag.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag/tag.tsx rename to x-pack/plugins/canvas/public/components/tag/tag.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag_list/__examples__/__snapshots__/tag_list.stories.storyshot b/x-pack/plugins/canvas/public/components/tag_list/__examples__/__snapshots__/tag_list.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag_list/__examples__/__snapshots__/tag_list.stories.storyshot rename to x-pack/plugins/canvas/public/components/tag_list/__examples__/__snapshots__/tag_list.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/tag_list/__examples__/tag_list.stories.tsx b/x-pack/plugins/canvas/public/components/tag_list/__examples__/tag_list.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag_list/__examples__/tag_list.stories.tsx rename to x-pack/plugins/canvas/public/components/tag_list/__examples__/tag_list.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag_list/index.tsx b/x-pack/plugins/canvas/public/components/tag_list/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag_list/index.tsx rename to x-pack/plugins/canvas/public/components/tag_list/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tag_list/tag_list.tsx b/x-pack/plugins/canvas/public/components/tag_list/tag_list.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tag_list/tag_list.tsx rename to x-pack/plugins/canvas/public/components/tag_list/tag_list.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/text_style_picker/font_sizes.js b/x-pack/plugins/canvas/public/components/text_style_picker/font_sizes.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/text_style_picker/font_sizes.js rename to x-pack/plugins/canvas/public/components/text_style_picker/font_sizes.js diff --git a/x-pack/legacy/plugins/canvas/public/components/text_style_picker/index.js b/x-pack/plugins/canvas/public/components/text_style_picker/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/text_style_picker/index.js rename to x-pack/plugins/canvas/public/components/text_style_picker/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js b/x-pack/plugins/canvas/public/components/text_style_picker/text_style_picker.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js rename to x-pack/plugins/canvas/public/components/text_style_picker/text_style_picker.js diff --git a/x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/__examples__/__snapshots__/tool_tip_shortcut.stories.storyshot b/x-pack/plugins/canvas/public/components/tool_tip_shortcut/__examples__/__snapshots__/tool_tip_shortcut.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/__examples__/__snapshots__/tool_tip_shortcut.stories.storyshot rename to x-pack/plugins/canvas/public/components/tool_tip_shortcut/__examples__/__snapshots__/tool_tip_shortcut.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/__examples__/tool_tip_shortcut.stories.tsx b/x-pack/plugins/canvas/public/components/tool_tip_shortcut/__examples__/tool_tip_shortcut.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/__examples__/tool_tip_shortcut.stories.tsx rename to x-pack/plugins/canvas/public/components/tool_tip_shortcut/__examples__/tool_tip_shortcut.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/index.tsx b/x-pack/plugins/canvas/public/components/tool_tip_shortcut/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/index.tsx rename to x-pack/plugins/canvas/public/components/tool_tip_shortcut/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/tool_tip_shortcut.tsx b/x-pack/plugins/canvas/public/components/tool_tip_shortcut/tool_tip_shortcut.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tool_tip_shortcut/tool_tip_shortcut.tsx rename to x-pack/plugins/canvas/public/components/tool_tip_shortcut/tool_tip_shortcut.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/__examples__/toolbar.stories.tsx b/x-pack/plugins/canvas/public/components/toolbar/__examples__/toolbar.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/__examples__/toolbar.stories.tsx rename to x-pack/plugins/canvas/public/components/toolbar/__examples__/toolbar.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/index.js b/x-pack/plugins/canvas/public/components/toolbar/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/index.js rename to x-pack/plugins/canvas/public/components/toolbar/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/toolbar.scss b/x-pack/plugins/canvas/public/components/toolbar/toolbar.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/toolbar.scss rename to x-pack/plugins/canvas/public/components/toolbar/toolbar.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/toolbar.tsx b/x-pack/plugins/canvas/public/components/toolbar/toolbar.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/toolbar.tsx rename to x-pack/plugins/canvas/public/components/toolbar/toolbar.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/tray/index.ts b/x-pack/plugins/canvas/public/components/toolbar/tray/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/tray/index.ts rename to x-pack/plugins/canvas/public/components/toolbar/tray/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/tray/tray.scss b/x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/tray/tray.scss rename to x-pack/plugins/canvas/public/components/toolbar/tray/tray.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/toolbar/tray/tray.tsx b/x-pack/plugins/canvas/public/components/toolbar/tray/tray.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/toolbar/tray/tray.tsx rename to x-pack/plugins/canvas/public/components/toolbar/tray/tray.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/index.js b/x-pack/plugins/canvas/public/components/tooltip_annotation/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/index.js rename to x-pack/plugins/canvas/public/components/tooltip_annotation/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.js b/x-pack/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.js rename to x-pack/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.js diff --git a/x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.scss b/x-pack/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.scss rename to x-pack/plugins/canvas/public/components/tooltip_annotation/tooltip_annotation.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/tooltip_icon/index.ts b/x-pack/plugins/canvas/public/components/tooltip_icon/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tooltip_icon/index.ts rename to x-pack/plugins/canvas/public/components/tooltip_icon/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/tooltip_icon/tooltip_icon.tsx b/x-pack/plugins/canvas/public/components/tooltip_icon/tooltip_icon.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/tooltip_icon/tooltip_icon.tsx rename to x-pack/plugins/canvas/public/components/tooltip_icon/tooltip_icon.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad/index.js b/x-pack/plugins/canvas/public/components/workpad/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad/index.js rename to x-pack/plugins/canvas/public/components/workpad/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad/workpad.js b/x-pack/plugins/canvas/public/components/workpad/workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad/workpad.js rename to x-pack/plugins/canvas/public/components/workpad/workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad/workpad.scss b/x-pack/plugins/canvas/public/components/workpad/workpad.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad/workpad.scss rename to x-pack/plugins/canvas/public/components/workpad/workpad.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/index.ts b/x-pack/plugins/canvas/public/components/workpad_color_picker/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/index.ts rename to x-pack/plugins/canvas/public/components/workpad_color_picker/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx b/x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx rename to x-pack/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_config/index.js b/x-pack/plugins/canvas/public/components/workpad_config/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_config/index.js rename to x-pack/plugins/canvas/public/components/workpad_config/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_config/workpad_config.js b/x-pack/plugins/canvas/public/components/workpad_config/workpad_config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_config/workpad_config.js rename to x-pack/plugins/canvas/public/components/workpad_config/workpad_config.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/__snapshots__/edit_menu.examples.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/__snapshots__/edit_menu.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/__snapshots__/edit_menu.examples.storyshot rename to x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/__snapshots__/edit_menu.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/edit_menu/__examples__/edit_menu.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/edit_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/edit_menu.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/edit_menu.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/edit_menu/edit_menu.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/edit_menu/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/edit_menu/index.ts rename to x-pack/plugins/canvas/public/components/workpad_header/edit_menu/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/__examples__/__snapshots__/element_menu.examples.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__examples__/__snapshots__/element_menu.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/__examples__/__snapshots__/element_menu.examples.storyshot rename to x-pack/plugins/canvas/public/components/workpad_header/element_menu/__examples__/__snapshots__/element_menu.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/__examples__/element_menu.examples.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__examples__/element_menu.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/__examples__/element_menu.examples.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/element_menu/__examples__/element_menu.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/element_menu.scss b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/element_menu.scss rename to x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/index.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.tsx similarity index 95% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/index.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.tsx index 40571a9341f69..a1227b3394678 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/element_menu/index.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; import { Dispatch } from 'redux'; -import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../src/plugins/kibana_react/public/'; import { State, ElementSpec } from '../../../../types'; // @ts-ignore Untyped local import { elementsRegistry } from '../../../lib/elements_registry'; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/fullscreen_control/fullscreen_control.tsx b/x-pack/plugins/canvas/public/components/workpad_header/fullscreen_control/fullscreen_control.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/fullscreen_control/fullscreen_control.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/fullscreen_control/fullscreen_control.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/fullscreen_control/index.js b/x-pack/plugins/canvas/public/components/workpad_header/fullscreen_control/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/fullscreen_control/index.js rename to x-pack/plugins/canvas/public/components/workpad_header/fullscreen_control/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/index.tsx b/x-pack/plugins/canvas/public/components/workpad_header/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/index.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/refresh_control/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/refresh_control/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/refresh_control/index.ts rename to x-pack/plugins/canvas/public/components/workpad_header/refresh_control/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/refresh_control/refresh_control.tsx b/x-pack/plugins/canvas/public/components/workpad_header/refresh_control/refresh_control.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/refresh_control/refresh_control.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/refresh_control/refresh_control.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/pdf_panel.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/pdf_panel.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/pdf_panel.stories.storyshot rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/pdf_panel.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/share_menu.examples.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/share_menu.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/share_menu.examples.storyshot rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/__snapshots__/share_menu.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/pdf_panel.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/pdf_panel.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/pdf_panel.stories.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/pdf_panel.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/share_menu.examples.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/share_menu.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/__examples__/share_menu.examples.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/__examples__/share_menu.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts index 4377635acac88..1ed39b62cccad 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/index.ts @@ -25,7 +25,7 @@ import { API_ROUTE_SHAREABLE_ZIP } from '../../../../../common/lib/constants'; import { renderFunctionNames } from '../../../../../shareable_runtime/supported_renderers'; import { ComponentStrings } from '../../../../../i18n/components'; -import { withKibana } from '../../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; import { OnCloseFn } from '../share_menu'; import { WithKibanaProps } from '../../../../index'; const { WorkpadHeaderShareMenu: strings } = ComponentStrings; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/runtime_step.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/runtime_step.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/runtime_step.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/runtime_step.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/share_website_flyout.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/share_website_flyout.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/share_website_flyout.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/share_website_flyout.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/snippets_step.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/snippets_step.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/snippets_step.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/snippets_step.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/workpad_step.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/workpad_step.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/flyout/workpad_step.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/flyout/workpad_step.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/index.ts similarity index 94% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/index.ts rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/index.ts index d6565f0e43db7..9a8936ada6d1e 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/index.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/index.ts @@ -6,14 +6,14 @@ import { connect } from 'react-redux'; import { compose, withProps } from 'recompose'; -import { jobCompletionNotifications } from '../../../../../../../plugins/reporting/public'; +import { jobCompletionNotifications } from '../../../../../../plugins/reporting/public'; import { getWorkpad, getPages } from '../../../state/selectors/workpad'; import { getWindow } from '../../../lib/get_window'; import { downloadWorkpad } from '../../../lib/download_workpad'; import { ShareMenu as Component, Props as ComponentProps } from './share_menu'; import { getPdfUrl, createPdf } from './utils'; import { State, CanvasWorkpad } from '../../../../types'; -import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../src/plugins/kibana_react/public/'; import { WithKibanaProps } from '../../../index'; import { ComponentStrings } from '../../../../i18n'; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/pdf_panel.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/pdf_panel.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/pdf_panel.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/pdf_panel.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/share_menu.scss b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/share_menu.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/share_menu.scss rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/share_menu.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/share_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/share_menu.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/share_menu.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/share_menu.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/utils.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/utils.ts rename to x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts index dc99c0687f388..8a3438e89e846 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/share_menu/utils.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.ts @@ -9,7 +9,7 @@ import rison from 'rison-node'; import { IBasePath } from 'kibana/public'; import { fetch } from '../../../../common/lib/fetch'; import { CanvasWorkpad } from '../../../../types'; -import { url } from '../../../../../../../../src/plugins/kibana_utils/public'; +import { url } from '../../../../../../../src/plugins/kibana_utils/public'; // type of the desired pdf output (print or preserve_layout) const PDF_LAYOUT_TYPE = 'preserve_layout'; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/__examples__/__snapshots__/view_menu.stories.storyshot b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/__examples__/__snapshots__/view_menu.stories.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/__examples__/__snapshots__/view_menu.stories.storyshot rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/__examples__/__snapshots__/view_menu.stories.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/__examples__/view_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/__examples__/view_menu.stories.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/__examples__/view_menu.stories.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/__examples__/view_menu.stories.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/auto_refresh_controls.tsx b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/auto_refresh_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/auto_refresh_controls.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/auto_refresh_controls.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/custom_interval.tsx b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/custom_interval.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/custom_interval.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/custom_interval.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/index.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/index.ts rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/index.ts index e1ad9782c8aef..e561607cb101e 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/index.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/index.ts @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import { compose, withHandlers } from 'recompose'; import { Dispatch } from 'redux'; -import { withKibana } from '../../../../../../../../src/plugins/kibana_react/public/'; +import { withKibana } from '../../../../../../../src/plugins/kibana_react/public/'; import { zoomHandlerCreators } from '../../../lib/app_handler_creators'; import { State, CanvasWorkpadBoundingBox } from '../../../../types'; // @ts-ignore Untyped local diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/kiosk_controls.tsx b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/kiosk_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/kiosk_controls.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/kiosk_controls.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/lib/get_fit_zoom_scale.ts b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/lib/get_fit_zoom_scale.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/lib/get_fit_zoom_scale.ts rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/lib/get_fit_zoom_scale.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/view_menu.scss b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/view_menu.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/view_menu.scss rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/view_menu.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/view_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/view_menu/view_menu.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/view_menu/view_menu.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/view_menu/view_menu.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_header/workpad_header.tsx rename to x-pack/plugins/canvas/public/components/workpad_header/workpad_header.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/index.js b/x-pack/plugins/canvas/public/components/workpad_loader/index.js similarity index 98% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/index.js rename to x-pack/plugins/canvas/public/components/workpad_loader/index.js index 9379379e54d97..8b190338db49e 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_loader/index.js @@ -14,7 +14,7 @@ import { getWorkpad } from '../../state/selectors/workpad'; import { getId } from '../../lib/get_id'; import { downloadWorkpad } from '../../lib/download_workpad'; import { ComponentStrings, ErrorStrings } from '../../../i18n'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { WorkpadLoader as Component } from './workpad_loader'; const { WorkpadLoader: strings } = ComponentStrings; diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/upload_workpad.js b/x-pack/plugins/canvas/public/components/workpad_loader/upload_workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/upload_workpad.js rename to x-pack/plugins/canvas/public/components/workpad_loader/upload_workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_create.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_create.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_create.js rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_create.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/index.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/index.js rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.js rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_dropzone/workpad_dropzone.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.js rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.scss b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_loader.scss rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_loader.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_search.js b/x-pack/plugins/canvas/public/components/workpad_loader/workpad_search.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_loader/workpad_search.js rename to x-pack/plugins/canvas/public/components/workpad_loader/workpad_search.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_manager/index.js b/x-pack/plugins/canvas/public/components/workpad_manager/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_manager/index.js rename to x-pack/plugins/canvas/public/components/workpad_manager/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_manager/workpad_manager.js b/x-pack/plugins/canvas/public/components/workpad_manager/workpad_manager.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_manager/workpad_manager.js rename to x-pack/plugins/canvas/public/components/workpad_manager/workpad_manager.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/index.js b/x-pack/plugins/canvas/public/components/workpad_page/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/index.js rename to x-pack/plugins/canvas/public/components/workpad_page/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/integration_utils.js b/x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/integration_utils.js rename to x-pack/plugins/canvas/public/components/workpad_page/integration_utils.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/positioning_utils.ts b/x-pack/plugins/canvas/public/components/workpad_page/positioning_utils.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/positioning_utils.ts rename to x-pack/plugins/canvas/public/components/workpad_page/positioning_utils.ts diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/prop_types.js b/x-pack/plugins/canvas/public/components/workpad_page/prop_types.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/prop_types.js rename to x-pack/plugins/canvas/public/components/workpad_page/prop_types.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/utils.js b/x-pack/plugins/canvas/public/components/workpad_page/utils.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/utils.js rename to x-pack/plugins/canvas/public/components/workpad_page/utils.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.js b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.js rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/event_handlers.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/index.js b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/index.js rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interaction_boundary.tsx b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interaction_boundary.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interaction_boundary.tsx rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interaction_boundary.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/interactive_workpad_page.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/workpad_interactive_page.scss b/x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/workpad_interactive_page.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_interactive_page/workpad_interactive_page.scss rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_interactive_page/workpad_interactive_page.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_page.scss b/x-pack/plugins/canvas/public/components/workpad_page/workpad_page.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_page.scss rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_page.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/index.js b/x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/index.js rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/index.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/static_workpad_page.js b/x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/static_workpad_page.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/static_workpad_page.js rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/static_workpad_page.js diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/workpad_static_page.scss b/x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/workpad_static_page.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_page/workpad_static_page/workpad_static_page.scss rename to x-pack/plugins/canvas/public/components/workpad_page/workpad_static_page/workpad_static_page.scss diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx b/x-pack/plugins/canvas/public/components/workpad_shortcuts/index.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/index.tsx rename to x-pack/plugins/canvas/public/components/workpad_shortcuts/index.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx b/x-pack/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx rename to x-pack/plugins/canvas/public/components/workpad_shortcuts/workpad_shortcuts.tsx diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_templates/index.js b/x-pack/plugins/canvas/public/components/workpad_templates/index.js similarity index 94% rename from x-pack/legacy/plugins/canvas/public/components/workpad_templates/index.js rename to x-pack/plugins/canvas/public/components/workpad_templates/index.js index 1890ca1f9d2d6..a17b77b74e499 100644 --- a/x-pack/legacy/plugins/canvas/public/components/workpad_templates/index.js +++ b/x-pack/plugins/canvas/public/components/workpad_templates/index.js @@ -9,7 +9,7 @@ import { compose, getContext, withHandlers, withProps } from 'recompose'; import * as workpadService from '../../lib/workpad_service'; import { getId } from '../../lib/get_id'; import { templatesRegistry } from '../../lib/templates_registry'; -import { withKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { withKibana } from '../../../../../../src/plugins/kibana_react/public'; import { WorkpadTemplates as Component } from './workpad_templates'; export const WorkpadTemplates = compose( diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js b/x-pack/plugins/canvas/public/components/workpad_templates/workpad_templates.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/components/workpad_templates/workpad_templates.js rename to x-pack/plugins/canvas/public/components/workpad_templates/workpad_templates.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg.js b/x-pack/plugins/canvas/public/expression_types/arg.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg.js rename to x-pack/plugins/canvas/public/expression_types/arg.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_type.js b/x-pack/plugins/canvas/public/expression_types/arg_type.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_type.js rename to x-pack/plugins/canvas/public/expression_types/arg_type.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js b/x-pack/plugins/canvas/public/expression_types/arg_types/color.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js rename to x-pack/plugins/canvas/public/expression_types/arg_types/color.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/simple_template.examples.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/simple_template.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/simple_template.examples.storyshot rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/simple_template.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/extended_template.examples.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/extended_template.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/extended_template.examples.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/extended_template.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/simple_template.examples.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/simple_template.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/simple_template.examples.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/simple_template.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/appearance_form.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/appearance_form.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/appearance_form.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/appearance_form.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/border_form.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/border_form.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/border_form.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/border_form.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/extended_template.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/extended_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/extended_template.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/extended_template.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/index.ts b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/index.ts rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/font.js b/x-pack/plugins/canvas/public/expression_types/arg_types/font.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/font.js rename to x-pack/plugins/canvas/public/expression_types/arg_types/font.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/index.js b/x-pack/plugins/canvas/public/expression_types/arg_types/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/index.js rename to x-pack/plugins/canvas/public/expression_types/arg_types/index.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/extended_template.examples.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/extended_template.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/extended_template.examples.storyshot rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/extended_template.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/__snapshots__/simple_template.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/extended_template.examples.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/extended_template.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/extended_template.examples.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/extended_template.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/simple_template.examples.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/simple_template.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/simple_template.examples.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/__examples__/simple_template.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/extended_template.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/extended_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/extended_template.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/extended_template.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/index.ts b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/index.ts rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx b/x-pack/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx rename to x-pack/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/base_form.js b/x-pack/plugins/canvas/public/expression_types/base_form.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/base_form.js rename to x-pack/plugins/canvas/public/expression_types/base_form.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/datasource.js b/x-pack/plugins/canvas/public/expression_types/datasource.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/datasource.js rename to x-pack/plugins/canvas/public/expression_types/datasource.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/function_form.js b/x-pack/plugins/canvas/public/expression_types/function_form.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/function_form.js rename to x-pack/plugins/canvas/public/expression_types/function_form.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/index.js b/x-pack/plugins/canvas/public/expression_types/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/index.js rename to x-pack/plugins/canvas/public/expression_types/index.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/model.js b/x-pack/plugins/canvas/public/expression_types/model.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/model.js rename to x-pack/plugins/canvas/public/expression_types/model.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/transform.js b/x-pack/plugins/canvas/public/expression_types/transform.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/transform.js rename to x-pack/plugins/canvas/public/expression_types/transform.js diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/view.js b/x-pack/plugins/canvas/public/expression_types/view.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/expression_types/view.js rename to x-pack/plugins/canvas/public/expression_types/view.js diff --git a/x-pack/legacy/plugins/canvas/public/feature_catalogue_entry.ts b/x-pack/plugins/canvas/public/feature_catalogue_entry.ts similarity index 87% rename from x-pack/legacy/plugins/canvas/public/feature_catalogue_entry.ts rename to x-pack/plugins/canvas/public/feature_catalogue_entry.ts index f610bd0299832..41506bdd71e3c 100644 --- a/x-pack/legacy/plugins/canvas/public/feature_catalogue_entry.ts +++ b/x-pack/plugins/canvas/public/feature_catalogue_entry.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { FeatureCatalogueCategory } from '../../../../../src/plugins/home/public'; +import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public'; export const featureCatalogueEntry = { id: 'canvas', diff --git a/x-pack/legacy/plugins/canvas/public/functions/__tests__/asset.js b/x-pack/plugins/canvas/public/functions/__tests__/asset.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/__tests__/asset.js rename to x-pack/plugins/canvas/public/functions/__tests__/asset.js diff --git a/x-pack/legacy/plugins/canvas/public/functions/asset.ts b/x-pack/plugins/canvas/public/functions/asset.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/asset.ts rename to x-pack/plugins/canvas/public/functions/asset.ts diff --git a/x-pack/legacy/plugins/canvas/public/functions/filters.ts b/x-pack/plugins/canvas/public/functions/filters.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/filters.ts rename to x-pack/plugins/canvas/public/functions/filters.ts diff --git a/x-pack/legacy/plugins/canvas/public/functions/index.ts b/x-pack/plugins/canvas/public/functions/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/index.ts rename to x-pack/plugins/canvas/public/functions/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/functions/timelion.ts b/x-pack/plugins/canvas/public/functions/timelion.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/timelion.ts rename to x-pack/plugins/canvas/public/functions/timelion.ts diff --git a/x-pack/legacy/plugins/canvas/public/functions/to.ts b/x-pack/plugins/canvas/public/functions/to.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/functions/to.ts rename to x-pack/plugins/canvas/public/functions/to.ts diff --git a/x-pack/legacy/plugins/canvas/public/icon.svg b/x-pack/plugins/canvas/public/icon.svg similarity index 100% rename from x-pack/legacy/plugins/canvas/public/icon.svg rename to x-pack/plugins/canvas/public/icon.svg diff --git a/x-pack/plugins/canvas/public/index.ts b/x-pack/plugins/canvas/public/index.ts index 736d5ccc0f8e5..d36f89354934a 100644 --- a/x-pack/plugins/canvas/public/index.ts +++ b/x-pack/plugins/canvas/public/index.ts @@ -5,6 +5,16 @@ */ import { PluginInitializerContext } from 'kibana/public'; -import { CanvasPlugin } from '../../../legacy/plugins/canvas/public/plugin'; +import { CoreStart } from '../../../../src/core/public'; +import { CanvasServices } from './services'; +import { CanvasSetup, CanvasStart, CanvasStartDeps, CanvasPlugin } from './plugin'; + +export { CanvasSetup, CanvasStart }; + +export interface WithKibanaProps { + kibana: { + services: CoreStart & CanvasStartDeps & { canvas: CanvasServices }; + }; +} export const plugin = (initializerContext: PluginInitializerContext) => new CanvasPlugin(); diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/find_expression_type.js b/x-pack/plugins/canvas/public/lib/__tests__/find_expression_type.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/find_expression_type.js rename to x-pack/plugins/canvas/public/lib/__tests__/find_expression_type.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/get_pretty_shortcut.test.ts b/x-pack/plugins/canvas/public/lib/__tests__/get_pretty_shortcut.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/get_pretty_shortcut.test.ts rename to x-pack/plugins/canvas/public/lib/__tests__/get_pretty_shortcut.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/history_provider.js b/x-pack/plugins/canvas/public/lib/__tests__/history_provider.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/history_provider.js rename to x-pack/plugins/canvas/public/lib/__tests__/history_provider.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/modify_path.js b/x-pack/plugins/canvas/public/lib/__tests__/modify_path.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/modify_path.js rename to x-pack/plugins/canvas/public/lib/__tests__/modify_path.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/readable_color.test.ts b/x-pack/plugins/canvas/public/lib/__tests__/readable_color.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/readable_color.test.ts rename to x-pack/plugins/canvas/public/lib/__tests__/readable_color.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/resolved_arg.js b/x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/resolved_arg.js rename to x-pack/plugins/canvas/public/lib/__tests__/resolved_arg.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/__tests__/time_interval.test.ts b/x-pack/plugins/canvas/public/lib/__tests__/time_interval.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/__tests__/time_interval.test.ts rename to x-pack/plugins/canvas/public/lib/__tests__/time_interval.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/__fixtures__/typescript/typespec_tests.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/common.js b/x-pack/plugins/canvas/public/lib/aeroelastic/common.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/common.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/common.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/functional.js b/x-pack/plugins/canvas/public/lib/aeroelastic/functional.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/functional.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/functional.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/geometry.js b/x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/geometry.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/geometry.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/gestures.js b/x-pack/plugins/canvas/public/lib/aeroelastic/gestures.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/gestures.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/gestures.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/index.d.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/index.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/index.d.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/index.d.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/layout.js b/x-pack/plugins/canvas/public/lib/aeroelastic/layout.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/layout.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/layout.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/layout_functions.js b/x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/layout_functions.js rename to x-pack/plugins/canvas/public/lib/aeroelastic/layout_functions.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/matrix.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/matrix.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/matrix.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/matrix.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/matrix2d.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/matrix2d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/matrix2d.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/matrix2d.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/select.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/select.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/select.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/select.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/store.ts b/x-pack/plugins/canvas/public/lib/aeroelastic/store.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/store.ts rename to x-pack/plugins/canvas/public/lib/aeroelastic/store.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/tsconfig.json b/x-pack/plugins/canvas/public/lib/aeroelastic/tsconfig.json similarity index 87% rename from x-pack/legacy/plugins/canvas/public/lib/aeroelastic/tsconfig.json rename to x-pack/plugins/canvas/public/lib/aeroelastic/tsconfig.json index ae5eb9321a59f..3b61e4b414626 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/aeroelastic/tsconfig.json +++ b/x-pack/plugins/canvas/public/lib/aeroelastic/tsconfig.json @@ -15,7 +15,7 @@ "paths": { "layout/*": ["aeroelastic/*"] }, - "types": ["@kbn/x-pack/legacy/plugins/canvas/public/lib/aeroelastic"] + "types": ["@kbn/x-pack/plugins/canvas/public/lib/aeroelastic"] }, "exclude": ["node_modules", "**/*.spec.ts", "node_modules/@types/mocha"] } diff --git a/x-pack/legacy/plugins/canvas/public/lib/app_handler_creators.ts b/x-pack/plugins/canvas/public/lib/app_handler_creators.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/app_handler_creators.ts rename to x-pack/plugins/canvas/public/lib/app_handler_creators.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/app_state.ts b/x-pack/plugins/canvas/public/lib/app_state.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/app_state.ts rename to x-pack/plugins/canvas/public/lib/app_state.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/arg_helpers.js b/x-pack/plugins/canvas/public/lib/arg_helpers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/arg_helpers.js rename to x-pack/plugins/canvas/public/lib/arg_helpers.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/breadcrumbs.ts b/x-pack/plugins/canvas/public/lib/breadcrumbs.ts similarity index 92% rename from x-pack/legacy/plugins/canvas/public/lib/breadcrumbs.ts rename to x-pack/plugins/canvas/public/lib/breadcrumbs.ts index 57b513affd781..96412ef50c79d 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/breadcrumbs.ts +++ b/x-pack/plugins/canvas/public/lib/breadcrumbs.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { ChromeBreadcrumb } from '../../../../../../src/core/public'; +import { ChromeBreadcrumb } from '../../../../../src/core/public'; import { platformService } from '../services'; export const getBaseBreadcrumb = () => ({ diff --git a/x-pack/legacy/plugins/canvas/public/lib/build_bool_array.js b/x-pack/plugins/canvas/public/lib/build_bool_array.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/build_bool_array.js rename to x-pack/plugins/canvas/public/lib/build_bool_array.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/build_embeddable_filters.test.ts b/x-pack/plugins/canvas/public/lib/build_embeddable_filters.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/build_embeddable_filters.test.ts rename to x-pack/plugins/canvas/public/lib/build_embeddable_filters.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/build_embeddable_filters.ts b/x-pack/plugins/canvas/public/lib/build_embeddable_filters.ts similarity index 92% rename from x-pack/legacy/plugins/canvas/public/lib/build_embeddable_filters.ts rename to x-pack/plugins/canvas/public/lib/build_embeddable_filters.ts index aa915d0d3d02a..9aa7477523c9a 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/build_embeddable_filters.ts +++ b/x-pack/plugins/canvas/public/lib/build_embeddable_filters.ts @@ -7,11 +7,7 @@ import { ExpressionValueFilter } from '../../types'; // @ts-ignore Untyped Local import { buildBoolArray } from './build_bool_array'; -import { - TimeRange, - esFilters, - Filter as DataFilter, -} from '../../../../../../src/plugins/data/public'; +import { TimeRange, esFilters, Filter as DataFilter } from '../../../../../src/plugins/data/public'; export interface EmbeddableFilterInput { filters: DataFilter[]; diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts b/x-pack/plugins/canvas/public/lib/clipboard.test.ts similarity index 86% rename from x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts rename to x-pack/plugins/canvas/public/lib/clipboard.test.ts index 54c3000dae36c..d10964003ed39 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/clipboard.test.ts +++ b/x-pack/plugins/canvas/public/lib/clipboard.test.ts @@ -3,9 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../../../../src/plugins/kibana_utils/public'); +jest.mock('../../../../../src/plugins/kibana_utils/public'); -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { setClipboardData, getClipboardData } from './clipboard'; import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; import { elements } from '../../__tests__/fixtures/workpads'; diff --git a/x-pack/legacy/plugins/canvas/public/lib/clipboard.ts b/x-pack/plugins/canvas/public/lib/clipboard.ts similarity index 90% rename from x-pack/legacy/plugins/canvas/public/lib/clipboard.ts rename to x-pack/plugins/canvas/public/lib/clipboard.ts index 50c5cdd0042fd..11755807aa533 100644 --- a/x-pack/legacy/plugins/canvas/public/lib/clipboard.ts +++ b/x-pack/plugins/canvas/public/lib/clipboard.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Storage } from '../../../../../../src/plugins/kibana_utils/public'; +import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; import { getWindow } from './get_window'; diff --git a/x-pack/legacy/plugins/canvas/public/lib/clone_subgraphs.js b/x-pack/plugins/canvas/public/lib/clone_subgraphs.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/clone_subgraphs.js rename to x-pack/plugins/canvas/public/lib/clone_subgraphs.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/custom_element_service.ts b/x-pack/plugins/canvas/public/lib/custom_element_service.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/custom_element_service.ts rename to x-pack/plugins/canvas/public/lib/custom_element_service.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/doc_title.js b/x-pack/plugins/canvas/public/lib/doc_title.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/doc_title.js rename to x-pack/plugins/canvas/public/lib/doc_title.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts b/x-pack/plugins/canvas/public/lib/documentation_links.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/documentation_links.ts rename to x-pack/plugins/canvas/public/lib/documentation_links.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/dom.ts b/x-pack/plugins/canvas/public/lib/dom.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/dom.ts rename to x-pack/plugins/canvas/public/lib/dom.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/download_workpad.ts b/x-pack/plugins/canvas/public/lib/download_workpad.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/download_workpad.ts rename to x-pack/plugins/canvas/public/lib/download_workpad.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/elastic_logo.ts b/x-pack/plugins/canvas/public/lib/elastic_logo.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/elastic_logo.ts rename to x-pack/plugins/canvas/public/lib/elastic_logo.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/elastic_outline.js b/x-pack/plugins/canvas/public/lib/elastic_outline.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/elastic_outline.js rename to x-pack/plugins/canvas/public/lib/elastic_outline.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/element.ts b/x-pack/plugins/canvas/public/lib/element.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/element.ts rename to x-pack/plugins/canvas/public/lib/element.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts b/x-pack/plugins/canvas/public/lib/element_handler_creators.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts rename to x-pack/plugins/canvas/public/lib/element_handler_creators.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/elements_registry.js b/x-pack/plugins/canvas/public/lib/elements_registry.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/elements_registry.js rename to x-pack/plugins/canvas/public/lib/elements_registry.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/es_service.ts b/x-pack/plugins/canvas/public/lib/es_service.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/es_service.ts rename to x-pack/plugins/canvas/public/lib/es_service.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/extract_search.js b/x-pack/plugins/canvas/public/lib/extract_search.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/extract_search.js rename to x-pack/plugins/canvas/public/lib/extract_search.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/filters.js b/x-pack/plugins/canvas/public/lib/filters.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/filters.js rename to x-pack/plugins/canvas/public/lib/filters.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/find_existing_asset.js b/x-pack/plugins/canvas/public/lib/find_existing_asset.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/find_existing_asset.js rename to x-pack/plugins/canvas/public/lib/find_existing_asset.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js b/x-pack/plugins/canvas/public/lib/find_expression_type.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/find_expression_type.js rename to x-pack/plugins/canvas/public/lib/find_expression_type.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/flatten_panel_tree.ts b/x-pack/plugins/canvas/public/lib/flatten_panel_tree.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/flatten_panel_tree.ts rename to x-pack/plugins/canvas/public/lib/flatten_panel_tree.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/fullscreen.js b/x-pack/plugins/canvas/public/lib/fullscreen.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/fullscreen.js rename to x-pack/plugins/canvas/public/lib/fullscreen.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_client_platform.ts b/x-pack/plugins/canvas/public/lib/get_client_platform.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_client_platform.ts rename to x-pack/plugins/canvas/public/lib/get_client_platform.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_es_filter.js b/x-pack/plugins/canvas/public/lib/get_es_filter.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_es_filter.js rename to x-pack/plugins/canvas/public/lib/get_es_filter.js diff --git a/x-pack/legacy/plugins/canvas/public/legacy_register_feature.ts b/x-pack/plugins/canvas/public/lib/get_id.ts similarity index 53% rename from x-pack/legacy/plugins/canvas/public/legacy_register_feature.ts rename to x-pack/plugins/canvas/public/lib/get_id.ts index 00f788f267d4b..0927a277f7caa 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy_register_feature.ts +++ b/x-pack/plugins/canvas/public/lib/get_id.ts @@ -4,11 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { npSetup } from 'ui/new_platform'; -import { featureCatalogueEntry } from './feature_catalogue_entry'; +import uuid from 'uuid/v4'; -const { - plugins: { home }, -} = npSetup; - -home.featureCatalogue.register(featureCatalogueEntry); +export function getId(type: string): string { + return `${type}-${uuid()}`; +} diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_pretty_shortcut.ts b/x-pack/plugins/canvas/public/lib/get_pretty_shortcut.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_pretty_shortcut.ts rename to x-pack/plugins/canvas/public/lib/get_pretty_shortcut.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_tags_filter.tsx b/x-pack/plugins/canvas/public/lib/get_tags_filter.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_tags_filter.tsx rename to x-pack/plugins/canvas/public/lib/get_tags_filter.tsx diff --git a/x-pack/legacy/plugins/canvas/public/lib/get_window.ts b/x-pack/plugins/canvas/public/lib/get_window.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/get_window.ts rename to x-pack/plugins/canvas/public/lib/get_window.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/history_provider.js b/x-pack/plugins/canvas/public/lib/history_provider.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/history_provider.js rename to x-pack/plugins/canvas/public/lib/history_provider.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/is_text_input.ts b/x-pack/plugins/canvas/public/lib/is_text_input.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/is_text_input.ts rename to x-pack/plugins/canvas/public/lib/is_text_input.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/keymap.ts b/x-pack/plugins/canvas/public/lib/keymap.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/keymap.ts rename to x-pack/plugins/canvas/public/lib/keymap.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/legend_options.js b/x-pack/plugins/canvas/public/lib/legend_options.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/legend_options.js rename to x-pack/plugins/canvas/public/lib/legend_options.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js b/x-pack/plugins/canvas/public/lib/load_expression_types.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/load_expression_types.js rename to x-pack/plugins/canvas/public/lib/load_expression_types.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/load_transitions.js b/x-pack/plugins/canvas/public/lib/load_transitions.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/load_transitions.js rename to x-pack/plugins/canvas/public/lib/load_transitions.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/loading_indicator.ts b/x-pack/plugins/canvas/public/lib/loading_indicator.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/loading_indicator.ts rename to x-pack/plugins/canvas/public/lib/loading_indicator.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/modify_path.js b/x-pack/plugins/canvas/public/lib/modify_path.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/modify_path.js rename to x-pack/plugins/canvas/public/lib/modify_path.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/modify_url.ts b/x-pack/plugins/canvas/public/lib/modify_url.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/modify_url.ts rename to x-pack/plugins/canvas/public/lib/modify_url.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/monaco_language_def.ts b/x-pack/plugins/canvas/public/lib/monaco_language_def.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/monaco_language_def.ts rename to x-pack/plugins/canvas/public/lib/monaco_language_def.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/parse_single_function_chain.js b/x-pack/plugins/canvas/public/lib/parse_single_function_chain.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/parse_single_function_chain.js rename to x-pack/plugins/canvas/public/lib/parse_single_function_chain.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/readable_color.ts b/x-pack/plugins/canvas/public/lib/readable_color.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/readable_color.ts rename to x-pack/plugins/canvas/public/lib/readable_color.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/resolved_arg.js b/x-pack/plugins/canvas/public/lib/resolved_arg.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/resolved_arg.js rename to x-pack/plugins/canvas/public/lib/resolved_arg.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/router_provider.js b/x-pack/plugins/canvas/public/lib/router_provider.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/router_provider.js rename to x-pack/plugins/canvas/public/lib/router_provider.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/run_interpreter.ts b/x-pack/plugins/canvas/public/lib/run_interpreter.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/run_interpreter.ts rename to x-pack/plugins/canvas/public/lib/run_interpreter.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/shortcut_manager.js b/x-pack/plugins/canvas/public/lib/shortcut_manager.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/shortcut_manager.js rename to x-pack/plugins/canvas/public/lib/shortcut_manager.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/sync_filter_expression.ts b/x-pack/plugins/canvas/public/lib/sync_filter_expression.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/sync_filter_expression.ts rename to x-pack/plugins/canvas/public/lib/sync_filter_expression.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/tag.ts b/x-pack/plugins/canvas/public/lib/tag.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/tag.ts rename to x-pack/plugins/canvas/public/lib/tag.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/tags_registry.ts b/x-pack/plugins/canvas/public/lib/tags_registry.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/tags_registry.ts rename to x-pack/plugins/canvas/public/lib/tags_registry.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/template.js b/x-pack/plugins/canvas/public/lib/template.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/template.js rename to x-pack/plugins/canvas/public/lib/template.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/template_from_react_component.tsx b/x-pack/plugins/canvas/public/lib/template_from_react_component.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/template_from_react_component.tsx rename to x-pack/plugins/canvas/public/lib/template_from_react_component.tsx diff --git a/x-pack/legacy/plugins/canvas/public/lib/templates_registry.js b/x-pack/plugins/canvas/public/lib/templates_registry.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/templates_registry.js rename to x-pack/plugins/canvas/public/lib/templates_registry.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/time_duration.ts b/x-pack/plugins/canvas/public/lib/time_duration.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/time_duration.ts rename to x-pack/plugins/canvas/public/lib/time_duration.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/time_interval.ts b/x-pack/plugins/canvas/public/lib/time_interval.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/time_interval.ts rename to x-pack/plugins/canvas/public/lib/time_interval.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/transitions_registry.js b/x-pack/plugins/canvas/public/lib/transitions_registry.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/transitions_registry.js rename to x-pack/plugins/canvas/public/lib/transitions_registry.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/ui_metric.ts b/x-pack/plugins/canvas/public/lib/ui_metric.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/ui_metric.ts rename to x-pack/plugins/canvas/public/lib/ui_metric.ts diff --git a/x-pack/legacy/plugins/canvas/public/lib/window_error_handler.js b/x-pack/plugins/canvas/public/lib/window_error_handler.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/window_error_handler.js rename to x-pack/plugins/canvas/public/lib/window_error_handler.js diff --git a/x-pack/legacy/plugins/canvas/public/lib/workpad_service.js b/x-pack/plugins/canvas/public/lib/workpad_service.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/lib/workpad_service.js rename to x-pack/plugins/canvas/public/lib/workpad_service.js diff --git a/x-pack/legacy/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx similarity index 80% rename from x-pack/legacy/plugins/canvas/public/plugin.tsx rename to x-pack/plugins/canvas/public/plugin.tsx index 1e85aad6328a5..6273aebe30e65 100644 --- a/x-pack/legacy/plugins/canvas/public/plugin.tsx +++ b/x-pack/plugins/canvas/public/plugin.tsx @@ -10,20 +10,19 @@ import { Plugin, AppMountParameters, DEFAULT_APP_CATEGORIES, -} from '../../../../../src/core/public'; -import { HomePublicPluginSetup } from '../../../../../src/plugins/home/public'; +} from '../../../../src/core/public'; +import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { initLoadingIndicator } from './lib/loading_indicator'; import { featureCatalogueEntry } from './feature_catalogue_entry'; -import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public'; -import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public'; -import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public'; -import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public'; -import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public'; -import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public'; +import { ExpressionsSetup, ExpressionsStart } from '../../../../src/plugins/expressions/public'; +import { DataPublicPluginSetup } from '../../../../src/plugins/data/public'; +import { UiActionsStart } from '../../../../src/plugins/ui_actions/public'; +import { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; +import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; +import { Start as InspectorStart } from '../../../../src/plugins/inspector/public'; // @ts-ignore untyped local import { argTypeSpecs } from './expression_types/arg_types'; import { transitions } from './transitions'; -import { legacyRegistries } from './legacy_plugin_support'; import { getPluginApi, CanvasApi } from './plugin_api'; import { initFunctions } from './functions'; import { CanvasSrcPlugin } from '../canvas_plugin_src/plugin'; @@ -95,11 +94,6 @@ export class CanvasPlugin plugins.home.featureCatalogue.register(featureCatalogueEntry); - // Register Legacy plugin stuff - canvasApi.addFunctions(legacyRegistries.browserFunctions.getOriginalFns()); - canvasApi.addElements(legacyRegistries.elements.getOriginalFns()); - canvasApi.addTypes(legacyRegistries.types.getOriginalFns()); - // Register core canvas stuff canvasApi.addFunctions( initFunctions({ diff --git a/x-pack/legacy/plugins/canvas/public/plugin_api.ts b/x-pack/plugins/canvas/public/plugin_api.ts similarity index 97% rename from x-pack/legacy/plugins/canvas/public/plugin_api.ts rename to x-pack/plugins/canvas/public/plugin_api.ts index a7346c0b4376e..738b319d29c0b 100644 --- a/x-pack/legacy/plugins/canvas/public/plugin_api.ts +++ b/x-pack/plugins/canvas/public/plugin_api.ts @@ -9,7 +9,7 @@ import { RendererFactory, } from '../types'; import { ElementFactory } from '../types'; -import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; +import { ExpressionsSetup } from '../../../../src/plugins/expressions/public'; type AddToRegistry = (add: T[]) => void; diff --git a/x-pack/legacy/plugins/canvas/public/registries.ts b/x-pack/plugins/canvas/public/registries.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/registries.ts rename to x-pack/plugins/canvas/public/registries.ts diff --git a/x-pack/legacy/plugins/canvas/public/services/index.ts b/x-pack/plugins/canvas/public/services/index.ts similarity index 96% rename from x-pack/legacy/plugins/canvas/public/services/index.ts rename to x-pack/plugins/canvas/public/services/index.ts index 17d836f1441c9..abc46beaa3e64 100644 --- a/x-pack/legacy/plugins/canvas/public/services/index.ts +++ b/x-pack/plugins/canvas/public/services/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup, CoreStart } from '../../../../../../src/core/public'; +import { CoreSetup, CoreStart } from '../../../../../src/core/public'; import { CanvasSetupDeps, CanvasStartDeps } from '../plugin'; import { notifyServiceFactory } from './notify'; import { platformServiceFactory } from './platform'; diff --git a/x-pack/legacy/plugins/canvas/public/services/notify.ts b/x-pack/plugins/canvas/public/services/notify.ts similarity index 91% rename from x-pack/legacy/plugins/canvas/public/services/notify.ts rename to x-pack/plugins/canvas/public/services/notify.ts index 3e18e2178a818..5454a0f87c3f0 100644 --- a/x-pack/legacy/plugins/canvas/public/services/notify.ts +++ b/x-pack/plugins/canvas/public/services/notify.ts @@ -6,8 +6,8 @@ import { get } from 'lodash'; import { CanvasServiceFactory } from '.'; -import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public'; -import { ToastInputFields } from '../../../../../../src/core/public'; +import { formatMsg } from '../../../../../src/plugins/kibana_legacy/public'; +import { ToastInputFields } from '../../../../../src/core/public'; const getToast = (err: Error | string, opts: ToastInputFields = {}) => { const errData = (get(err, 'response') || err) as Error | string; diff --git a/x-pack/legacy/plugins/canvas/public/services/platform.ts b/x-pack/plugins/canvas/public/services/platform.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/services/platform.ts rename to x-pack/plugins/canvas/public/services/platform.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js b/x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js rename to x-pack/plugins/canvas/public/state/actions/__tests__/elements.get_sibling_context.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/app.js b/x-pack/plugins/canvas/public/state/actions/app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/app.js rename to x-pack/plugins/canvas/public/state/actions/app.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/assets.js b/x-pack/plugins/canvas/public/state/actions/assets.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/assets.js rename to x-pack/plugins/canvas/public/state/actions/assets.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/elements.js b/x-pack/plugins/canvas/public/state/actions/elements.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/elements.js rename to x-pack/plugins/canvas/public/state/actions/elements.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/embeddable.ts b/x-pack/plugins/canvas/public/state/actions/embeddable.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/embeddable.ts rename to x-pack/plugins/canvas/public/state/actions/embeddable.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/history.js b/x-pack/plugins/canvas/public/state/actions/history.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/history.js rename to x-pack/plugins/canvas/public/state/actions/history.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/pages.js b/x-pack/plugins/canvas/public/state/actions/pages.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/pages.js rename to x-pack/plugins/canvas/public/state/actions/pages.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/resolved_args.ts b/x-pack/plugins/canvas/public/state/actions/resolved_args.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/resolved_args.ts rename to x-pack/plugins/canvas/public/state/actions/resolved_args.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/transient.js b/x-pack/plugins/canvas/public/state/actions/transient.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/transient.js rename to x-pack/plugins/canvas/public/state/actions/transient.js diff --git a/x-pack/legacy/plugins/canvas/public/state/actions/workpad.js b/x-pack/plugins/canvas/public/state/actions/workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/actions/workpad.js rename to x-pack/plugins/canvas/public/state/actions/workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/state/defaults.js b/x-pack/plugins/canvas/public/state/defaults.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/defaults.js rename to x-pack/plugins/canvas/public/state/defaults.js diff --git a/x-pack/legacy/plugins/canvas/public/state/initial_state.js b/x-pack/plugins/canvas/public/state/initial_state.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/initial_state.js rename to x-pack/plugins/canvas/public/state/initial_state.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts b/x-pack/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts rename to x-pack/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts b/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts rename to x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts b/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts similarity index 99% rename from x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts rename to x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts index 2123c9606f1f0..f90f570bc6ebf 100644 --- a/x-pack/legacy/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts +++ b/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../legacy'); jest.mock('ui/new_platform'); // actions/elements has some dependencies on ui/new_platform. jest.mock('../../../lib/app_state'); diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/app_ready.js b/x-pack/plugins/canvas/public/state/middleware/app_ready.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/app_ready.js rename to x-pack/plugins/canvas/public/state/middleware/app_ready.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/breadcrumbs.js b/x-pack/plugins/canvas/public/state/middleware/breadcrumbs.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/breadcrumbs.js rename to x-pack/plugins/canvas/public/state/middleware/breadcrumbs.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/element_stats.js b/x-pack/plugins/canvas/public/state/middleware/element_stats.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/element_stats.js rename to x-pack/plugins/canvas/public/state/middleware/element_stats.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/es_persist.js b/x-pack/plugins/canvas/public/state/middleware/es_persist.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/es_persist.js rename to x-pack/plugins/canvas/public/state/middleware/es_persist.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/fullscreen.js b/x-pack/plugins/canvas/public/state/middleware/fullscreen.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/fullscreen.js rename to x-pack/plugins/canvas/public/state/middleware/fullscreen.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/history.js b/x-pack/plugins/canvas/public/state/middleware/history.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/history.js rename to x-pack/plugins/canvas/public/state/middleware/history.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/in_flight.ts b/x-pack/plugins/canvas/public/state/middleware/in_flight.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/in_flight.ts rename to x-pack/plugins/canvas/public/state/middleware/in_flight.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/index.js b/x-pack/plugins/canvas/public/state/middleware/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/index.js rename to x-pack/plugins/canvas/public/state/middleware/index.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/resolved_args.js b/x-pack/plugins/canvas/public/state/middleware/resolved_args.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/resolved_args.js rename to x-pack/plugins/canvas/public/state/middleware/resolved_args.js diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/workpad_autoplay.ts b/x-pack/plugins/canvas/public/state/middleware/workpad_autoplay.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/workpad_autoplay.ts rename to x-pack/plugins/canvas/public/state/middleware/workpad_autoplay.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/workpad_refresh.ts b/x-pack/plugins/canvas/public/state/middleware/workpad_refresh.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/workpad_refresh.ts rename to x-pack/plugins/canvas/public/state/middleware/workpad_refresh.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/middleware/workpad_update.js b/x-pack/plugins/canvas/public/state/middleware/workpad_update.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/middleware/workpad_update.js rename to x-pack/plugins/canvas/public/state/middleware/workpad_update.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/elements.js b/x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/elements.js rename to x-pack/plugins/canvas/public/state/reducers/__tests__/elements.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/fixtures/action_creator.js b/x-pack/plugins/canvas/public/state/reducers/__tests__/fixtures/action_creator.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/fixtures/action_creator.js rename to x-pack/plugins/canvas/public/state/reducers/__tests__/fixtures/action_creator.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/resolved_args.js b/x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/__tests__/resolved_args.js rename to x-pack/plugins/canvas/public/state/reducers/__tests__/resolved_args.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/app.js b/x-pack/plugins/canvas/public/state/reducers/app.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/app.js rename to x-pack/plugins/canvas/public/state/reducers/app.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/assets.js b/x-pack/plugins/canvas/public/state/reducers/assets.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/assets.js rename to x-pack/plugins/canvas/public/state/reducers/assets.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/elements.js b/x-pack/plugins/canvas/public/state/reducers/elements.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/elements.js rename to x-pack/plugins/canvas/public/state/reducers/elements.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/embeddable.ts b/x-pack/plugins/canvas/public/state/reducers/embeddable.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/embeddable.ts rename to x-pack/plugins/canvas/public/state/reducers/embeddable.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/embeddables.test.ts b/x-pack/plugins/canvas/public/state/reducers/embeddables.test.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/embeddables.test.ts rename to x-pack/plugins/canvas/public/state/reducers/embeddables.test.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/history.js b/x-pack/plugins/canvas/public/state/reducers/history.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/history.js rename to x-pack/plugins/canvas/public/state/reducers/history.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/index.js b/x-pack/plugins/canvas/public/state/reducers/index.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/index.js rename to x-pack/plugins/canvas/public/state/reducers/index.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/pages.js b/x-pack/plugins/canvas/public/state/reducers/pages.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/pages.js rename to x-pack/plugins/canvas/public/state/reducers/pages.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/resolved_args.js b/x-pack/plugins/canvas/public/state/reducers/resolved_args.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/resolved_args.js rename to x-pack/plugins/canvas/public/state/reducers/resolved_args.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/transient.js b/x-pack/plugins/canvas/public/state/reducers/transient.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/transient.js rename to x-pack/plugins/canvas/public/state/reducers/transient.js diff --git a/x-pack/legacy/plugins/canvas/public/state/reducers/workpad.js b/x-pack/plugins/canvas/public/state/reducers/workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/reducers/workpad.js rename to x-pack/plugins/canvas/public/state/reducers/workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/__tests__/resolved_args.js b/x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/selectors/__tests__/resolved_args.js rename to x-pack/plugins/canvas/public/state/selectors/__tests__/resolved_args.js diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/__tests__/workpad.js b/x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/selectors/__tests__/workpad.js rename to x-pack/plugins/canvas/public/state/selectors/__tests__/workpad.js diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/app.ts b/x-pack/plugins/canvas/public/state/selectors/app.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/selectors/app.ts rename to x-pack/plugins/canvas/public/state/selectors/app.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/assets.ts b/x-pack/plugins/canvas/public/state/selectors/assets.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/selectors/assets.ts rename to x-pack/plugins/canvas/public/state/selectors/assets.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/resolved_args.ts b/x-pack/plugins/canvas/public/state/selectors/resolved_args.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/selectors/resolved_args.ts rename to x-pack/plugins/canvas/public/state/selectors/resolved_args.ts diff --git a/x-pack/legacy/plugins/canvas/public/state/selectors/workpad.ts b/x-pack/plugins/canvas/public/state/selectors/workpad.ts similarity index 99% rename from x-pack/legacy/plugins/canvas/public/state/selectors/workpad.ts rename to x-pack/plugins/canvas/public/state/selectors/workpad.ts index 80a7c34e8bef5..ae5c0fee52062 100644 --- a/x-pack/legacy/plugins/canvas/public/state/selectors/workpad.ts +++ b/x-pack/plugins/canvas/public/state/selectors/workpad.ts @@ -16,12 +16,10 @@ import { CanvasGroup, PositionedElement, CanvasWorkpadBoundingBox, -} from '../../../types'; -import { ExpressionAstArgument, ExpressionAstFunction, ExpressionAstExpression, -} from '../../../../../../../src/plugins/expressions/common'; +} from '../../../types'; type Modify = Pick> & R; type WorkpadInfo = Modify; diff --git a/x-pack/legacy/plugins/canvas/public/state/store.js b/x-pack/plugins/canvas/public/state/store.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/state/store.js rename to x-pack/plugins/canvas/public/state/store.js diff --git a/x-pack/legacy/plugins/canvas/public/store.ts b/x-pack/plugins/canvas/public/store.ts similarity index 94% rename from x-pack/legacy/plugins/canvas/public/store.ts rename to x-pack/plugins/canvas/public/store.ts index 1460932101725..8560e612de4db 100644 --- a/x-pack/legacy/plugins/canvas/public/store.ts +++ b/x-pack/plugins/canvas/public/store.ts @@ -9,7 +9,7 @@ import { createStore as createReduxStore, destroyStore as destroy } from './stat // @ts-ignore Untyped local import { getInitialState } from './state/initial_state'; -import { CoreSetup } from '../../../../../src/core/public'; +import { CoreSetup } from '../../../../src/core/public'; import { CanvasSetupDeps } from './plugin'; export async function createStore(core: CoreSetup, plugins: CanvasSetupDeps) { diff --git a/x-pack/legacy/plugins/canvas/public/style/hackery.scss b/x-pack/plugins/canvas/public/style/hackery.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/style/hackery.scss rename to x-pack/plugins/canvas/public/style/hackery.scss diff --git a/x-pack/legacy/plugins/canvas/public/style/index.scss b/x-pack/plugins/canvas/public/style/index.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/style/index.scss rename to x-pack/plugins/canvas/public/style/index.scss diff --git a/x-pack/legacy/plugins/canvas/public/style/main.scss b/x-pack/plugins/canvas/public/style/main.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/style/main.scss rename to x-pack/plugins/canvas/public/style/main.scss diff --git a/x-pack/legacy/plugins/canvas/public/transitions/fade/fade.scss b/x-pack/plugins/canvas/public/transitions/fade/fade.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/fade/fade.scss rename to x-pack/plugins/canvas/public/transitions/fade/fade.scss diff --git a/x-pack/legacy/plugins/canvas/public/transitions/fade/index.ts b/x-pack/plugins/canvas/public/transitions/fade/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/fade/index.ts rename to x-pack/plugins/canvas/public/transitions/fade/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/transitions/index.ts b/x-pack/plugins/canvas/public/transitions/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/index.ts rename to x-pack/plugins/canvas/public/transitions/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/transitions/rotate/index.ts b/x-pack/plugins/canvas/public/transitions/rotate/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/rotate/index.ts rename to x-pack/plugins/canvas/public/transitions/rotate/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/transitions/rotate/rotate.scss b/x-pack/plugins/canvas/public/transitions/rotate/rotate.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/rotate/rotate.scss rename to x-pack/plugins/canvas/public/transitions/rotate/rotate.scss diff --git a/x-pack/legacy/plugins/canvas/public/transitions/slide/index.ts b/x-pack/plugins/canvas/public/transitions/slide/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/slide/index.ts rename to x-pack/plugins/canvas/public/transitions/slide/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/transitions/slide/slide.scss b/x-pack/plugins/canvas/public/transitions/slide/slide.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/slide/slide.scss rename to x-pack/plugins/canvas/public/transitions/slide/slide.scss diff --git a/x-pack/legacy/plugins/canvas/public/transitions/transition.js b/x-pack/plugins/canvas/public/transitions/transition.js similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/transition.js rename to x-pack/plugins/canvas/public/transitions/transition.js diff --git a/x-pack/legacy/plugins/canvas/public/transitions/zoom/index.ts b/x-pack/plugins/canvas/public/transitions/zoom/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/zoom/index.ts rename to x-pack/plugins/canvas/public/transitions/zoom/index.ts diff --git a/x-pack/legacy/plugins/canvas/public/transitions/zoom/zoom.scss b/x-pack/plugins/canvas/public/transitions/zoom/zoom.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/public/transitions/zoom/zoom.scss rename to x-pack/plugins/canvas/public/transitions/zoom/zoom.scss diff --git a/x-pack/legacy/plugins/canvas/scripts/_helpers.js b/x-pack/plugins/canvas/scripts/_helpers.js similarity index 78% rename from x-pack/legacy/plugins/canvas/scripts/_helpers.js rename to x-pack/plugins/canvas/scripts/_helpers.js index dea58e90cc60b..0f4b07d988308 100644 --- a/x-pack/legacy/plugins/canvas/scripts/_helpers.js +++ b/x-pack/plugins/canvas/scripts/_helpers.js @@ -7,19 +7,19 @@ const { resolve } = require('path'); exports.runGulpTask = function(name) { - process.chdir(resolve(__dirname, '../../../..')); + process.chdir(resolve(__dirname, '../../..')); process.argv.splice(1, 1, require.resolve('gulp/bin/gulp'), name); require('gulp/bin/gulp'); }; exports.runKibanaScript = function(name, args = []) { - process.chdir(resolve(__dirname, '../../../../..')); + process.chdir(resolve(__dirname, '../../../..')); process.argv.splice(2, 0, ...args); - require('../../../../../scripts/' + name); // eslint-disable-line import/no-dynamic-require + require('../../../../scripts/' + name); // eslint-disable-line import/no-dynamic-require }; exports.runXPackScript = function(name, args = []) { - process.chdir(resolve(__dirname, '../../../..')); + process.chdir(resolve(__dirname, '../../..')); process.argv.splice(2, 0, ...args); - require('../../../../scripts/' + name); // eslint-disable-line import/no-dynamic-require + require('../../../scripts/' + name); // eslint-disable-line import/no-dynamic-require }; diff --git a/x-pack/legacy/plugins/canvas/scripts/jest.js b/x-pack/plugins/canvas/scripts/jest.js similarity index 94% rename from x-pack/legacy/plugins/canvas/scripts/jest.js rename to x-pack/plugins/canvas/scripts/jest.js index 133f775c7192f..b30cb02d2c99a 100644 --- a/x-pack/legacy/plugins/canvas/scripts/jest.js +++ b/x-pack/plugins/canvas/scripts/jest.js @@ -19,9 +19,9 @@ run( if (path) { log.info(`Limiting tests to ${path}...`); - path = 'legacy/plugins/canvas/' + path; + path = 'plugins/canvas/' + path; } else { - path = 'legacy/plugins/canvas'; + path = 'plugins/canvas'; } if (coverage) { @@ -49,7 +49,7 @@ run( '--collectCoverageFrom', // Include TS/X files `${path}/**/*.ts*`, '--coverageDirectory', // Output to canvas/coverage - 'legacy/plugins/canvas/coverage', + 'plugins/canvas/coverage', ]; } // Mitigation for https://github.com/facebook/jest/issues/7267 @@ -60,7 +60,7 @@ run( if (all) { log.info('Running all available tests. This will take a while...'); } else if (storybook) { - path = 'legacy/plugins/canvas/.storybook'; + path = 'plugins/canvas/.storybook'; log.info('Running Storybook Snapshot tests...'); } else { log.info('Running tests. This does not include Storybook Snapshots...'); diff --git a/x-pack/legacy/plugins/canvas/scripts/kbn.js b/x-pack/plugins/canvas/scripts/kbn.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/kbn.js rename to x-pack/plugins/canvas/scripts/kbn.js diff --git a/x-pack/legacy/plugins/canvas/scripts/lint.js b/x-pack/plugins/canvas/scripts/lint.js similarity index 69% rename from x-pack/legacy/plugins/canvas/scripts/lint.js rename to x-pack/plugins/canvas/scripts/lint.js index effc654712e6c..6d40c100ddfb5 100644 --- a/x-pack/legacy/plugins/canvas/scripts/lint.js +++ b/x-pack/plugins/canvas/scripts/lint.js @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -require('./_helpers').runKibanaScript('eslint', [ - 'x-pack/legacy/plugins/canvas/**/*.{js,jsx,ts,tsx}', -]); +require('./_helpers').runKibanaScript('eslint', ['x-pack/plugins/canvas/**/*.{js,jsx,ts,tsx}']); diff --git a/x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js b/x-pack/plugins/canvas/scripts/shareable_runtime.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/shareable_runtime.js rename to x-pack/plugins/canvas/scripts/shareable_runtime.js diff --git a/x-pack/legacy/plugins/canvas/scripts/storybook.js b/x-pack/plugins/canvas/scripts/storybook.js similarity index 92% rename from x-pack/legacy/plugins/canvas/scripts/storybook.js rename to x-pack/plugins/canvas/scripts/storybook.js index a6369d1e72fac..c9e6c6c65436c 100644 --- a/x-pack/legacy/plugins/canvas/scripts/storybook.js +++ b/x-pack/plugins/canvas/scripts/storybook.js @@ -37,7 +37,7 @@ run( // Ensure SASS dependencies have been built before doing anything. execa.sync(process.execPath, ['scripts/build_sass'], { - cwd: path.resolve(__dirname, '../../../../..'), + cwd: path.resolve(__dirname, '../../../..'), ...options, }); @@ -51,14 +51,14 @@ run( [ 'webpack', '--config', - 'x-pack/legacy/plugins/canvas/.storybook/webpack.dll.config.js', + 'x-pack/plugins/canvas/.storybook/webpack.dll.config.js', '--progress', '--hide-modules', '--display-entrypoints', 'false', ], { - cwd: path.resolve(__dirname, '../../../../..'), + cwd: path.resolve(__dirname, '../../../..'), stdio: ['ignore', 'inherit', 'inherit'], buffer: false, } @@ -96,7 +96,7 @@ run( // Watch the SASS sheets for changes execa(process.execPath, ['scripts/build_sass', '--watch'], { - cwd: path.resolve(__dirname, '../../../../..'), + cwd: path.resolve(__dirname, '../../../..'), ...options, }); diff --git a/x-pack/legacy/plugins/canvas/scripts/storybook_new.js b/x-pack/plugins/canvas/scripts/storybook_new.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/storybook_new.js rename to x-pack/plugins/canvas/scripts/storybook_new.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test.js b/x-pack/plugins/canvas/scripts/test.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test.js rename to x-pack/plugins/canvas/scripts/test.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test_browser.js b/x-pack/plugins/canvas/scripts/test_browser.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test_browser.js rename to x-pack/plugins/canvas/scripts/test_browser.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test_common.js b/x-pack/plugins/canvas/scripts/test_common.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test_common.js rename to x-pack/plugins/canvas/scripts/test_common.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test_dev.js b/x-pack/plugins/canvas/scripts/test_dev.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test_dev.js rename to x-pack/plugins/canvas/scripts/test_dev.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test_plugins.js b/x-pack/plugins/canvas/scripts/test_plugins.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test_plugins.js rename to x-pack/plugins/canvas/scripts/test_plugins.js diff --git a/x-pack/legacy/plugins/canvas/scripts/test_server.js b/x-pack/plugins/canvas/scripts/test_server.js similarity index 100% rename from x-pack/legacy/plugins/canvas/scripts/test_server.js rename to x-pack/plugins/canvas/scripts/test_server.js diff --git a/x-pack/plugins/canvas/server/collectors/collector.ts b/x-pack/plugins/canvas/server/collectors/collector.ts index 8e9e5ede2e7f2..88e5e43dc2af1 100644 --- a/x-pack/plugins/canvas/server/collectors/collector.ts +++ b/x-pack/plugins/canvas/server/collectors/collector.ts @@ -6,7 +6,7 @@ import { CallCluster } from 'src/legacy/core_plugins/elasticsearch'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { CANVAS_USAGE_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_USAGE_TYPE } from '../../common/lib/constants'; import { TelemetryCollector } from '../../types'; import { workpadCollector } from './workpad_collector'; diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts index 70bc074ff3df8..420b785771bfe 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts @@ -6,7 +6,7 @@ import clonedeep from 'lodash.clonedeep'; import { summarizeWorkpads } from './workpad_collector'; -import { workpads } from '../../../../legacy/plugins/canvas/__tests__/fixtures/workpads'; +import { workpads } from '../../__tests__/fixtures/workpads'; describe('usage collector handle es response data', () => { it('should summarize workpads, pages, and elements', () => { diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts index 9c088958c748f..b14a35ded4781 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts @@ -6,7 +6,7 @@ import { SearchParams } from 'elasticsearch'; import { sum as arraySum, min as arrayMin, max as arrayMax, get } from 'lodash'; -import { CANVAS_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../common/lib/constants'; import { collectFns } from './collector_helpers'; import { TelemetryCollector, CanvasWorkpad } from '../../types'; import { parseExpression } from '../../../../../src/plugins/expressions/common'; diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/create.test.ts b/x-pack/plugins/canvas/server/routes/custom_elements/create.test.ts index d3a69c01732fa..c260d6ca8ac16 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/create.test.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/create.test.ts @@ -11,7 +11,7 @@ import { httpServerMock, loggingServiceMock, } from 'src/core/server/mocks'; -import { CUSTOM_ELEMENT_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE } from '../../../common/lib/constants'; import { initializeCreateCustomElementRoute } from './create'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/create.ts b/x-pack/plugins/canvas/server/routes/custom_elements/create.ts index b882829124696..1c3b9221c52cd 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/create.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/create.ts @@ -5,11 +5,8 @@ */ import { RouteInitializerDeps } from '../'; -import { - CUSTOM_ELEMENT_TYPE, - API_ROUTE_CUSTOM_ELEMENT, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; -import { getId } from '../../../../../legacy/plugins/canvas/public/lib/get_id'; +import { CUSTOM_ELEMENT_TYPE, API_ROUTE_CUSTOM_ELEMENT } from '../../../common/lib/constants'; +import { getId } from '../../../common/lib/get_id'; import { CustomElementSchema } from './custom_element_schema'; import { CustomElementAttributes } from './custom_element_attributes'; import { okResponse } from '../ok_response'; diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/custom_element_attributes.ts b/x-pack/plugins/canvas/server/routes/custom_elements/custom_element_attributes.ts index e76526eeeb27b..772ebb1d79a5e 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/custom_element_attributes.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/custom_element_attributes.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CustomElement } from '../../../../../legacy/plugins/canvas/types'; +import { CustomElement } from '../../../types'; // Exclude ID attribute for the type used for SavedObjectClient export type CustomElementAttributes = Pick> & { diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/delete.test.ts b/x-pack/plugins/canvas/server/routes/custom_elements/delete.test.ts index c108f2316db27..e70fae5d18eaf 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/delete.test.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/delete.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CUSTOM_ELEMENT_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE } from '../../../common/lib/constants'; import { initializeDeleteCustomElementRoute } from './delete'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/delete.ts b/x-pack/plugins/canvas/server/routes/custom_elements/delete.ts index 5867539b95b53..b9d52ccfbac80 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/delete.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/delete.ts @@ -6,10 +6,7 @@ import { schema } from '@kbn/config-schema'; import { RouteInitializerDeps } from '../'; -import { - CUSTOM_ELEMENT_TYPE, - API_ROUTE_CUSTOM_ELEMENT, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE, API_ROUTE_CUSTOM_ELEMENT } from '../../../common/lib/constants'; import { okResponse } from '../ok_response'; import { catchErrorHandler } from '../catch_error_handler'; diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/find.ts b/x-pack/plugins/canvas/server/routes/custom_elements/find.ts index 5041ceb3e4711..964618adf165d 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/find.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/find.ts @@ -7,10 +7,7 @@ import { schema } from '@kbn/config-schema'; import { SavedObjectAttributes } from 'src/core/server'; import { RouteInitializerDeps } from '../'; -import { - CUSTOM_ELEMENT_TYPE, - API_ROUTE_CUSTOM_ELEMENT, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE, API_ROUTE_CUSTOM_ELEMENT } from '../../../common/lib/constants'; export function initializeFindCustomElementsRoute(deps: RouteInitializerDeps) { const { router } = deps; diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/get.test.ts b/x-pack/plugins/canvas/server/routes/custom_elements/get.test.ts index 5e8d536f779a9..03ae6048801bf 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/get.test.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/get.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CUSTOM_ELEMENT_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE } from '../../../common/lib/constants'; import { initializeGetCustomElementRoute } from './get'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/get.ts b/x-pack/plugins/canvas/server/routes/custom_elements/get.ts index f092b001e141f..bb8e320a7c124 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/get.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/get.ts @@ -6,10 +6,7 @@ import { schema } from '@kbn/config-schema'; import { RouteInitializerDeps } from '../'; -import { - CUSTOM_ELEMENT_TYPE, - API_ROUTE_CUSTOM_ELEMENT, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE, API_ROUTE_CUSTOM_ELEMENT } from '../../../common/lib/constants'; import { CustomElementAttributes } from './custom_element_attributes'; import { catchErrorHandler } from '../catch_error_handler'; diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/update.test.ts b/x-pack/plugins/canvas/server/routes/custom_elements/update.test.ts index 285a998030cf6..e67e42c26cd2b 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/update.test.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/update.test.ts @@ -5,8 +5,8 @@ */ import sinon from 'sinon'; -import { CustomElement } from '../../../../../legacy/plugins/canvas/types'; -import { CUSTOM_ELEMENT_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CustomElement } from '../../../types'; +import { CUSTOM_ELEMENT_TYPE } from '../../../common/lib/constants'; import { initializeUpdateCustomElementRoute } from './update'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/custom_elements/update.ts b/x-pack/plugins/canvas/server/routes/custom_elements/update.ts index 51c363249dd79..a65d23d8c1406 100644 --- a/x-pack/plugins/canvas/server/routes/custom_elements/update.ts +++ b/x-pack/plugins/canvas/server/routes/custom_elements/update.ts @@ -7,10 +7,7 @@ import { schema } from '@kbn/config-schema'; import { omit } from 'lodash'; import { RouteInitializerDeps } from '../'; -import { - CUSTOM_ELEMENT_TYPE, - API_ROUTE_CUSTOM_ELEMENT, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE, API_ROUTE_CUSTOM_ELEMENT } from '../../../common/lib/constants'; import { CustomElementUpdateSchema } from './custom_element_schema'; import { CustomElementAttributes } from './custom_element_attributes'; import { okResponse } from '../ok_response'; diff --git a/x-pack/plugins/canvas/server/routes/es_fields/es_fields.ts b/x-pack/plugins/canvas/server/routes/es_fields/es_fields.ts index 5282a246de6b6..5ebf20095bf3e 100644 --- a/x-pack/plugins/canvas/server/routes/es_fields/es_fields.ts +++ b/x-pack/plugins/canvas/server/routes/es_fields/es_fields.ts @@ -6,7 +6,7 @@ import { mapValues, keys } from 'lodash'; import { schema } from '@kbn/config-schema'; -import { API_ROUTE } from '../../../../../legacy/plugins/canvas/common/lib'; +import { API_ROUTE } from '../../../common/lib'; import { catchErrorHandler } from '../catch_error_handler'; // @ts-ignore unconverted lib import { normalizeType } from '../../lib/normalize_type'; diff --git a/x-pack/plugins/canvas/server/routes/shareables/download.ts b/x-pack/plugins/canvas/server/routes/shareables/download.ts index 08bec1e4881ae..3f331c1635e16 100644 --- a/x-pack/plugins/canvas/server/routes/shareables/download.ts +++ b/x-pack/plugins/canvas/server/routes/shareables/download.ts @@ -5,9 +5,9 @@ */ import { readFileSync } from 'fs'; -import { SHAREABLE_RUNTIME_FILE } from '../../../../../legacy/plugins/canvas/shareable_runtime/constants'; +import { SHAREABLE_RUNTIME_FILE } from '../../../shareable_runtime/constants'; import { RouteInitializerDeps } from '../'; -import { API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD } from '../../../common/lib/constants'; export function initializeDownloadShareableWorkpadRoute(deps: RouteInitializerDeps) { const { router } = deps; diff --git a/x-pack/plugins/canvas/server/routes/shareables/zip.test.ts b/x-pack/plugins/canvas/server/routes/shareables/zip.test.ts index edb59694a7400..63776f897a04c 100644 --- a/x-pack/plugins/canvas/server/routes/shareables/zip.test.ts +++ b/x-pack/plugins/canvas/server/routes/shareables/zip.test.ts @@ -15,12 +15,12 @@ import { } from 'src/core/server'; import { httpServiceMock, httpServerMock, loggingServiceMock } from 'src/core/server/mocks'; import { initializeZipShareableWorkpadRoute } from './zip'; -import { API_ROUTE_SHAREABLE_ZIP } from '../../../../../legacy/plugins/canvas/common/lib'; +import { API_ROUTE_SHAREABLE_ZIP } from '../../../common/lib'; import { SHAREABLE_RUNTIME_FILE, SHAREABLE_RUNTIME_SRC, SHAREABLE_RUNTIME_NAME, -} from '../../../../../legacy/plugins/canvas/shareable_runtime/constants'; +} from '../../../shareable_runtime/constants'; const mockRouteContext = {} as RequestHandlerContext; const mockWorkpad = {}; diff --git a/x-pack/plugins/canvas/server/routes/shareables/zip.ts b/x-pack/plugins/canvas/server/routes/shareables/zip.ts index e25b96cce96ff..99f401cd4c142 100644 --- a/x-pack/plugins/canvas/server/routes/shareables/zip.ts +++ b/x-pack/plugins/canvas/server/routes/shareables/zip.ts @@ -5,12 +5,12 @@ */ import archiver from 'archiver'; -import { API_ROUTE_SHAREABLE_ZIP } from '../../../../../legacy/plugins/canvas/common/lib'; +import { API_ROUTE_SHAREABLE_ZIP } from '../../../common/lib'; import { SHAREABLE_RUNTIME_FILE, SHAREABLE_RUNTIME_NAME, SHAREABLE_RUNTIME_SRC, -} from '../../../../../legacy/plugins/canvas/shareable_runtime/constants'; +} from '../../../shareable_runtime/constants'; import { RenderedWorkpadSchema } from './rendered_workpad_schema'; import { RouteInitializerDeps } from '..'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/create.test.ts b/x-pack/plugins/canvas/server/routes/workpad/create.test.ts index dbad1a97dc458..02b6376ece2ed 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/create.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/create.test.ts @@ -11,7 +11,7 @@ import { httpServerMock, loggingServiceMock, } from 'src/core/server/mocks'; -import { CANVAS_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeCreateWorkpadRoute } from './create'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/workpad/create.ts b/x-pack/plugins/canvas/server/routes/workpad/create.ts index 1e9a320c0eeef..5a693c05b3112 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/create.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/create.ts @@ -5,12 +5,9 @@ */ import { RouteInitializerDeps } from '../'; -import { - CANVAS_TYPE, - API_ROUTE_WORKPAD, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; -import { CanvasWorkpad } from '../../../../../legacy/plugins/canvas/types'; -import { getId } from '../../../../../legacy/plugins/canvas/public/lib/get_id'; +import { CANVAS_TYPE, API_ROUTE_WORKPAD } from '../../../common/lib/constants'; +import { CanvasWorkpad } from '../../../types'; +import { getId } from '../../../common/lib/get_id'; import { WorkpadAttributes } from './workpad_attributes'; import { WorkpadSchema } from './workpad_schema'; import { okResponse } from '../ok_response'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/delete.test.ts b/x-pack/plugins/canvas/server/routes/workpad/delete.test.ts index e693840826b7a..57df4e7cffda6 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/delete.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/delete.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CANVAS_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeDeleteWorkpadRoute } from './delete'; import { IRouter, diff --git a/x-pack/plugins/canvas/server/routes/workpad/delete.ts b/x-pack/plugins/canvas/server/routes/workpad/delete.ts index 8de4ea0f9a27f..52c95c2f42d30 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/delete.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/delete.ts @@ -6,10 +6,7 @@ import { schema } from '@kbn/config-schema'; import { RouteInitializerDeps } from '../'; -import { - CANVAS_TYPE, - API_ROUTE_WORKPAD, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE, API_ROUTE_WORKPAD } from '../../../common/lib/constants'; import { okResponse } from '../ok_response'; import { catchErrorHandler } from '../catch_error_handler'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/find.ts b/x-pack/plugins/canvas/server/routes/workpad/find.ts index a528a75611609..ec5c068a1fa24 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/find.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/find.ts @@ -7,10 +7,7 @@ import { schema } from '@kbn/config-schema'; import { SavedObjectAttributes } from 'src/core/server'; import { RouteInitializerDeps } from '../'; -import { - CANVAS_TYPE, - API_ROUTE_WORKPAD, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE, API_ROUTE_WORKPAD } from '../../../common/lib/constants'; export function initializeFindWorkpadsRoute(deps: RouteInitializerDeps) { const { router } = deps; diff --git a/x-pack/plugins/canvas/server/routes/workpad/get.test.ts b/x-pack/plugins/canvas/server/routes/workpad/get.test.ts index a31293f572c75..6741f2b3fc9d6 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/get.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/get.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CANVAS_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeGetWorkpadRoute } from './get'; import { IRouter, @@ -18,8 +18,8 @@ import { httpServerMock, loggingServiceMock, } from 'src/core/server/mocks'; -import { workpadWithGroupAsElement } from '../../../../../legacy/plugins/canvas/__tests__/fixtures/workpads'; -import { CanvasWorkpad } from '../../../../../legacy/plugins/canvas/types'; +import { workpadWithGroupAsElement } from '../../../__tests__/fixtures/workpads'; +import { CanvasWorkpad } from '../../../types'; const mockRouteContext = ({ core: { diff --git a/x-pack/plugins/canvas/server/routes/workpad/get.ts b/x-pack/plugins/canvas/server/routes/workpad/get.ts index d7a5e77670f6e..7dc1252063e90 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/get.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/get.ts @@ -6,10 +6,7 @@ import { schema } from '@kbn/config-schema'; import { RouteInitializerDeps } from '../'; -import { - CANVAS_TYPE, - API_ROUTE_WORKPAD, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE, API_ROUTE_WORKPAD } from '../../../common/lib/constants'; import { WorkpadAttributes } from './workpad_attributes'; import { catchErrorHandler } from '../catch_error_handler'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/update.test.ts b/x-pack/plugins/canvas/server/routes/workpad/update.test.ts index de098dd9717ed..a6b34e7165121 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/update.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/update.test.ts @@ -5,7 +5,7 @@ */ import sinon from 'sinon'; -import { CANVAS_TYPE } from '../../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeUpdateWorkpadRoute, initializeUpdateWorkpadAssetsRoute } from './update'; import { IRouter, @@ -19,7 +19,7 @@ import { httpServerMock, loggingServiceMock, } from 'src/core/server/mocks'; -import { workpads } from '../../../../../legacy/plugins/canvas/__tests__/fixtures/workpads'; +import { workpads } from '../../../__tests__/fixtures/workpads'; import { okResponse } from '../ok_response'; const mockRouteContext = ({ diff --git a/x-pack/plugins/canvas/server/routes/workpad/update.ts b/x-pack/plugins/canvas/server/routes/workpad/update.ts index 64736bcd57fd5..021ac41d88d19 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/update.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/update.ts @@ -13,7 +13,7 @@ import { API_ROUTE_WORKPAD, API_ROUTE_WORKPAD_STRUCTURES, API_ROUTE_WORKPAD_ASSETS, -} from '../../../../../legacy/plugins/canvas/common/lib/constants'; +} from '../../../common/lib/constants'; import { WorkpadAttributes } from './workpad_attributes'; import { WorkpadSchema, WorkpadAssetSchema } from './workpad_schema'; import { okResponse } from '../ok_response'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/workpad_attributes.ts b/x-pack/plugins/canvas/server/routes/workpad/workpad_attributes.ts index 2b7b6cca4ba2b..fd811adeebbd8 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/workpad_attributes.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/workpad_attributes.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CanvasWorkpad } from '../../../../../legacy/plugins/canvas/types'; +import { CanvasWorkpad } from '../../../types'; export type WorkpadAttributes = Pick> & { '@timestamp': string; diff --git a/x-pack/plugins/canvas/server/saved_objects/custom_element.ts b/x-pack/plugins/canvas/server/saved_objects/custom_element.ts index d26f6dd8fb16e..5fe48e98f28da 100644 --- a/x-pack/plugins/canvas/server/saved_objects/custom_element.ts +++ b/x-pack/plugins/canvas/server/saved_objects/custom_element.ts @@ -5,7 +5,7 @@ */ import { SavedObjectsType } from 'src/core/server'; -import { CUSTOM_ELEMENT_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; +import { CUSTOM_ELEMENT_TYPE } from '../../common/lib/constants'; export const customElementType: SavedObjectsType = { name: CUSTOM_ELEMENT_TYPE, diff --git a/x-pack/plugins/canvas/server/saved_objects/workpad.ts b/x-pack/plugins/canvas/server/saved_objects/workpad.ts index 2e9570b1b83be..3c8486f3246b2 100644 --- a/x-pack/plugins/canvas/server/saved_objects/workpad.ts +++ b/x-pack/plugins/canvas/server/saved_objects/workpad.ts @@ -5,7 +5,7 @@ */ import { SavedObjectsType } from 'src/core/server'; -import { CANVAS_TYPE } from '../../../../legacy/plugins/canvas/common/lib/constants'; +import { CANVAS_TYPE } from '../../common/lib/constants'; import { removeAttributesId } from './migrations/remove_attributes_id'; export const workpadType: SavedObjectsType = { diff --git a/x-pack/plugins/canvas/server/setup_interpreter.ts b/x-pack/plugins/canvas/server/setup_interpreter.ts index 74dd8decbea69..79bc2f3c1996b 100644 --- a/x-pack/plugins/canvas/server/setup_interpreter.ts +++ b/x-pack/plugins/canvas/server/setup_interpreter.ts @@ -5,7 +5,7 @@ */ import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; -import { functions } from '../../../legacy/plugins/canvas/canvas_plugin_src/functions/server'; +import { functions } from '../canvas_plugin_src/functions/server'; export function setupInterpreter(expressions: ExpressionsServerSetup) { expressions.__LEGACY.register({ types: [], serverFunctions: functions }); diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/README.md b/x-pack/plugins/canvas/shareable_runtime/README.md similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/README.md rename to x-pack/plugins/canvas/shareable_runtime/README.md diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/__mocks__/supported_renderers.js b/x-pack/plugins/canvas/shareable_runtime/__mocks__/supported_renderers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/__mocks__/supported_renderers.js rename to x-pack/plugins/canvas/shareable_runtime/__mocks__/supported_renderers.js diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap rename to x-pack/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx b/x-pack/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/api/index.ts b/x-pack/plugins/canvas/shareable_runtime/api/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/api/index.ts rename to x-pack/plugins/canvas/shareable_runtime/api/index.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/api/shareable.tsx b/x-pack/plugins/canvas/shareable_runtime/api/shareable.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/api/shareable.tsx rename to x-pack/plugins/canvas/shareable_runtime/api/shareable.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/canvas.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/canvas.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/canvas.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/canvas.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/page.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/page.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/page.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/page.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/rendered_element.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/rendered_element.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/rendered_element.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/__snapshots__/rendered_element.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/canvas.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/canvas.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/canvas.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/canvas.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/page.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/page.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/page.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/page.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/rendered_element.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__examples__/rendered_element.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__examples__/rendered_element.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__examples__/rendered_element.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap rename to x-pack/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/app.tsx b/x-pack/plugins/canvas/shareable_runtime/components/app.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/app.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/app.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/canvas.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/canvas.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/canvas.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/canvas.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/canvas.tsx b/x-pack/plugins/canvas/shareable_runtime/components/canvas.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/canvas.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/canvas.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.components.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.components.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.components.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.components.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/footer.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/page_controls.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/page_controls.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/page_controls.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/page_controls.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/scrubber.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/scrubber.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/scrubber.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/scrubber.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/title.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/title.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/title.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/__snapshots__/title.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/footer.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/footer.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/footer.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/footer.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/page_controls.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/page_controls.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/page_controls.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/page_controls.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/scrubber.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/scrubber.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/scrubber.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/scrubber.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/title.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/title.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__examples__/title.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__examples__/title.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/footer.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/page_controls.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/page_controls.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/page_controls.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/page_controls.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/page_preview.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/page_preview.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/page_preview.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/page_preview.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/scrubber.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/scrubber.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/scrubber.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/scrubber.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/title.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/title.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/__tests__/title.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/__tests__/title.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/footer.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/footer.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/footer/footer.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/footer.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/footer.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/footer.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/footer.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/index.ts b/x-pack/plugins/canvas/shareable_runtime/components/footer/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/index.ts rename to x-pack/plugins/canvas/shareable_runtime/components/footer/index.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_controls.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/page_controls.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_controls.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/page_controls.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_preview.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/footer/page_preview.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_preview.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/footer/page_preview.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_preview.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/page_preview.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/page_preview.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/page_preview.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/scrubber.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/scrubber.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/scrubber.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/autoplay_settings.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.components.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.components.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.components.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.components.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/settings.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/toolbar_settings.examples.storyshot b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/toolbar_settings.examples.storyshot similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/toolbar_settings.examples.storyshot rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/__snapshots__/toolbar_settings.examples.storyshot diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/autoplay_settings.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/autoplay_settings.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/autoplay_settings.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/autoplay_settings.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/settings.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/settings.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/settings.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/settings.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/toolbar_settings.examples.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/toolbar_settings.examples.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/toolbar_settings.examples.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__examples__/toolbar_settings.examples.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/__snapshots__/settings.test.tsx.snap diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/autoplay_settings.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/autoplay_settings.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/autoplay_settings.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/autoplay_settings.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/toolbar_settings.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/toolbar_settings.test.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/toolbar_settings.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/toolbar_settings.test.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/autoplay_settings.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/autoplay_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/autoplay_settings.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/autoplay_settings.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/index.ts b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/index.ts rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/index.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/settings.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/settings.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/settings.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/toolbar_settings.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/settings/toolbar_settings.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/toolbar_settings.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/settings/toolbar_settings.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/title.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/title.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/title.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/footer/title.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/page.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/page.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/page.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/page.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/page.tsx b/x-pack/plugins/canvas/shareable_runtime/components/page.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/page.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/page.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/rendered_element.module.scss b/x-pack/plugins/canvas/shareable_runtime/components/rendered_element.module.scss similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/rendered_element.module.scss rename to x-pack/plugins/canvas/shareable_runtime/components/rendered_element.module.scss diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/rendered_element.tsx b/x-pack/plugins/canvas/shareable_runtime/components/rendered_element.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/components/rendered_element.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/rendered_element.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/constants.d.ts b/x-pack/plugins/canvas/shareable_runtime/constants.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/constants.d.ts rename to x-pack/plugins/canvas/shareable_runtime/constants.d.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/constants.js b/x-pack/plugins/canvas/shareable_runtime/constants.js similarity index 92% rename from x-pack/legacy/plugins/canvas/shareable_runtime/constants.js rename to x-pack/plugins/canvas/shareable_runtime/constants.js index 2ac92f57a90ed..98abc7ca5a95f 100644 --- a/x-pack/legacy/plugins/canvas/shareable_runtime/constants.js +++ b/x-pack/plugins/canvas/shareable_runtime/constants.js @@ -7,8 +7,8 @@ const path = require('path'); const { LIBRARY_NAME, SHAREABLE_RUNTIME_NAME } = require('./constants_static'); -const KIBANA_ROOT_PATH = '../../../../..'; -const CANVAS_ROOT_PATH = 'x-pack/legacy/plugins/canvas'; +const KIBANA_ROOT_PATH = '../../../..'; +const CANVAS_ROOT_PATH = 'x-pack/plugins/canvas'; const SHAREABLE_RUNTIME_PATH = 'shareable_runtime'; const SHAREABLE_RUNTIME_OUTPUT_PATH = 'shareable_runtime/build'; const SHAREABLE_RUNTIME_FILE_PATH = 'shareable_runtime/build/kbn_canvas.js'; diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/constants_static.d.ts b/x-pack/plugins/canvas/shareable_runtime/constants_static.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/constants_static.d.ts rename to x-pack/plugins/canvas/shareable_runtime/constants_static.d.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/constants_static.js b/x-pack/plugins/canvas/shareable_runtime/constants_static.js similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/constants_static.js rename to x-pack/plugins/canvas/shareable_runtime/constants_static.js diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/context/actions.ts b/x-pack/plugins/canvas/shareable_runtime/context/actions.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/context/actions.ts rename to x-pack/plugins/canvas/shareable_runtime/context/actions.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/context/index.ts b/x-pack/plugins/canvas/shareable_runtime/context/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/context/index.ts rename to x-pack/plugins/canvas/shareable_runtime/context/index.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/context/reducer.ts b/x-pack/plugins/canvas/shareable_runtime/context/reducer.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/context/reducer.ts rename to x-pack/plugins/canvas/shareable_runtime/context/reducer.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/context/state.tsx b/x-pack/plugins/canvas/shareable_runtime/context/state.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/context/state.tsx rename to x-pack/plugins/canvas/shareable_runtime/context/state.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/css_modules.d.ts b/x-pack/plugins/canvas/shareable_runtime/css_modules.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/css_modules.d.ts rename to x-pack/plugins/canvas/shareable_runtime/css_modules.d.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/index.html b/x-pack/plugins/canvas/shareable_runtime/index.html similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/index.html rename to x-pack/plugins/canvas/shareable_runtime/index.html diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/index.ts b/x-pack/plugins/canvas/shareable_runtime/index.ts similarity index 81% rename from x-pack/legacy/plugins/canvas/shareable_runtime/index.ts rename to x-pack/plugins/canvas/shareable_runtime/index.ts index 2398a348f5a31..8b29b23c4442f 100644 --- a/x-pack/legacy/plugins/canvas/shareable_runtime/index.ts +++ b/x-pack/plugins/canvas/shareable_runtime/index.ts @@ -5,13 +5,13 @@ */ export * from './api'; -import '../../../../../built_assets/css/plugins/kibana/index.light.css'; +import '../../../../built_assets/css/plugins/kibana/index.light.css'; import '../public/style/index.scss'; import '@elastic/eui/dist/eui_theme_light.css'; import '@kbn/ui-framework/dist/kui_light.css'; const css = require.context( - '../../../../../built_assets/css', + '../../../../built_assets/css', true, /\.\/plugins\/(?!canvas).*light\.css/ ); @@ -20,7 +20,7 @@ css.keys().forEach(filename => { }); const uiStyles = require.context( - '../../../../../src/legacy/ui/public/styles', + '../../../../src/legacy/ui/public/styles', false, /[\/\\](?!mixins|variables|_|\.|bootstrap_(light|dark))[^\/\\]+\.less/ ); diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/postcss.config.js b/x-pack/plugins/canvas/shareable_runtime/postcss.config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/postcss.config.js rename to x-pack/plugins/canvas/shareable_runtime/postcss.config.js diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/supported_renderers.d.ts b/x-pack/plugins/canvas/shareable_runtime/supported_renderers.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/supported_renderers.d.ts rename to x-pack/plugins/canvas/shareable_runtime/supported_renderers.d.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/supported_renderers.js b/x-pack/plugins/canvas/shareable_runtime/supported_renderers.js similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/supported_renderers.js rename to x-pack/plugins/canvas/shareable_runtime/supported_renderers.js diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/template.html b/x-pack/plugins/canvas/shareable_runtime/template.html similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/template.html rename to x-pack/plugins/canvas/shareable_runtime/template.html diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/context.tsx b/x-pack/plugins/canvas/shareable_runtime/test/context.tsx similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/context.tsx rename to x-pack/plugins/canvas/shareable_runtime/test/context.tsx diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/context_example.ts b/x-pack/plugins/canvas/shareable_runtime/test/context_example.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/context_example.ts rename to x-pack/plugins/canvas/shareable_runtime/test/context_example.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/context_jest.ts b/x-pack/plugins/canvas/shareable_runtime/test/context_jest.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/context_jest.ts rename to x-pack/plugins/canvas/shareable_runtime/test/context_jest.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/index.ts b/x-pack/plugins/canvas/shareable_runtime/test/index.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/index.ts rename to x-pack/plugins/canvas/shareable_runtime/test/index.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/interactions.ts b/x-pack/plugins/canvas/shareable_runtime/test/interactions.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/interactions.ts rename to x-pack/plugins/canvas/shareable_runtime/test/interactions.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/selectors.ts b/x-pack/plugins/canvas/shareable_runtime/test/selectors.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/selectors.ts rename to x-pack/plugins/canvas/shareable_runtime/test/selectors.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/utils.ts b/x-pack/plugins/canvas/shareable_runtime/test/utils.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/utils.ts rename to x-pack/plugins/canvas/shareable_runtime/test/utils.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/austin.json b/x-pack/plugins/canvas/shareable_runtime/test/workpads/austin.json similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/austin.json rename to x-pack/plugins/canvas/shareable_runtime/test/workpads/austin.json diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/hello.json b/x-pack/plugins/canvas/shareable_runtime/test/workpads/hello.json similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/hello.json rename to x-pack/plugins/canvas/shareable_runtime/test/workpads/hello.json diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/test.json b/x-pack/plugins/canvas/shareable_runtime/test/workpads/test.json similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/test/workpads/test.json rename to x-pack/plugins/canvas/shareable_runtime/test/workpads/test.json diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/types.ts b/x-pack/plugins/canvas/shareable_runtime/types.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/types.ts rename to x-pack/plugins/canvas/shareable_runtime/types.ts diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/webpack.config.js b/x-pack/plugins/canvas/shareable_runtime/webpack.config.js similarity index 100% rename from x-pack/legacy/plugins/canvas/shareable_runtime/webpack.config.js rename to x-pack/plugins/canvas/shareable_runtime/webpack.config.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/customElementService.js b/x-pack/plugins/canvas/tasks/mocks/customElementService.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/customElementService.js rename to x-pack/plugins/canvas/tasks/mocks/customElementService.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/downloadWorkpad.js b/x-pack/plugins/canvas/tasks/mocks/downloadWorkpad.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/downloadWorkpad.js rename to x-pack/plugins/canvas/tasks/mocks/downloadWorkpad.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/uiAbsoluteToParsedUrl.ts b/x-pack/plugins/canvas/tasks/mocks/uiAbsoluteToParsedUrl.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/uiAbsoluteToParsedUrl.ts rename to x-pack/plugins/canvas/tasks/mocks/uiAbsoluteToParsedUrl.ts diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/uiChrome.js b/x-pack/plugins/canvas/tasks/mocks/uiChrome.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/uiChrome.js rename to x-pack/plugins/canvas/tasks/mocks/uiChrome.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/uiMetric.js b/x-pack/plugins/canvas/tasks/mocks/uiMetric.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/uiMetric.js rename to x-pack/plugins/canvas/tasks/mocks/uiMetric.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/uiNotify.js b/x-pack/plugins/canvas/tasks/mocks/uiNotify.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/uiNotify.js rename to x-pack/plugins/canvas/tasks/mocks/uiNotify.js diff --git a/x-pack/legacy/plugins/canvas/tasks/mocks/uiNotifyFormatMsg.js b/x-pack/plugins/canvas/tasks/mocks/uiNotifyFormatMsg.js similarity index 100% rename from x-pack/legacy/plugins/canvas/tasks/mocks/uiNotifyFormatMsg.js rename to x-pack/plugins/canvas/tasks/mocks/uiNotifyFormatMsg.js diff --git a/x-pack/legacy/plugins/canvas/types/arguments.ts b/x-pack/plugins/canvas/types/arguments.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/arguments.ts rename to x-pack/plugins/canvas/types/arguments.ts diff --git a/x-pack/legacy/plugins/canvas/types/assets.ts b/x-pack/plugins/canvas/types/assets.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/assets.ts rename to x-pack/plugins/canvas/types/assets.ts diff --git a/x-pack/legacy/plugins/canvas/types/canvas.ts b/x-pack/plugins/canvas/types/canvas.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/canvas.ts rename to x-pack/plugins/canvas/types/canvas.ts diff --git a/x-pack/legacy/plugins/canvas/types/elements.ts b/x-pack/plugins/canvas/types/elements.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/elements.ts rename to x-pack/plugins/canvas/types/elements.ts diff --git a/x-pack/legacy/plugins/canvas/types/functions.ts b/x-pack/plugins/canvas/types/functions.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/functions.ts rename to x-pack/plugins/canvas/types/functions.ts diff --git a/x-pack/legacy/plugins/canvas/types/global.d.ts b/x-pack/plugins/canvas/types/global.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/global.d.ts rename to x-pack/plugins/canvas/types/global.d.ts diff --git a/x-pack/plugins/canvas/types/index.ts b/x-pack/plugins/canvas/types/index.ts index 014b203754a21..0799627ce9b5a 100644 --- a/x-pack/plugins/canvas/types/index.ts +++ b/x-pack/plugins/canvas/types/index.ts @@ -4,4 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from '../../../legacy/plugins/canvas/types'; +export * from '../../../../src/plugins/expressions/common'; +export * from './assets'; +export * from './canvas'; +export * from './elements'; +export * from './functions'; +export * from './renderers'; +export * from './shortcuts'; +export * from './state'; +export * from './style'; +export * from './telemetry'; diff --git a/x-pack/legacy/plugins/canvas/types/react_moment_prototypes.d.ts b/x-pack/plugins/canvas/types/react_moment_prototypes.d.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/react_moment_prototypes.d.ts rename to x-pack/plugins/canvas/types/react_moment_prototypes.d.ts diff --git a/x-pack/legacy/plugins/canvas/types/renderers.ts b/x-pack/plugins/canvas/types/renderers.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/renderers.ts rename to x-pack/plugins/canvas/types/renderers.ts diff --git a/x-pack/legacy/plugins/canvas/types/shortcuts.ts b/x-pack/plugins/canvas/types/shortcuts.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/shortcuts.ts rename to x-pack/plugins/canvas/types/shortcuts.ts diff --git a/x-pack/legacy/plugins/canvas/types/state.ts b/x-pack/plugins/canvas/types/state.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/state.ts rename to x-pack/plugins/canvas/types/state.ts diff --git a/x-pack/legacy/plugins/canvas/types/style.ts b/x-pack/plugins/canvas/types/style.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/style.ts rename to x-pack/plugins/canvas/types/style.ts diff --git a/x-pack/legacy/plugins/canvas/types/telemetry.ts b/x-pack/plugins/canvas/types/telemetry.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/telemetry.ts rename to x-pack/plugins/canvas/types/telemetry.ts diff --git a/x-pack/legacy/plugins/canvas/types/transforms.ts b/x-pack/plugins/canvas/types/transforms.ts similarity index 100% rename from x-pack/legacy/plugins/canvas/types/transforms.ts rename to x-pack/plugins/canvas/types/transforms.ts diff --git a/x-pack/plugins/siem/scripts/optimize_tsconfig/tsconfig.json b/x-pack/plugins/siem/scripts/optimize_tsconfig/tsconfig.json index fb89c0e0fc3e2..fb838d82f14ed 100644 --- a/x-pack/plugins/siem/scripts/optimize_tsconfig/tsconfig.json +++ b/x-pack/plugins/siem/scripts/optimize_tsconfig/tsconfig.json @@ -3,7 +3,7 @@ "typings/**/*", "plugins/siem/**/*", "plugins/apm/typings/numeral.d.ts", - "legacy/plugins/canvas/types/webpack.d.ts", + "plugins/canvas/types/webpack.d.ts", "plugins/triggers_actions_ui/**/*" ], "exclude": [ diff --git a/x-pack/tasks/build.ts b/x-pack/tasks/build.ts index ca03e1c9fd283..38ebb0bad4bdc 100644 --- a/x-pack/tasks/build.ts +++ b/x-pack/tasks/build.ts @@ -30,7 +30,7 @@ async function cleanBuildTask() { await del(BUILD_DIR); fancyLog('[canvas] Deleting Shareable Runtime'); - await del(resolve(XPACK_DIR, 'legacy/plugins/canvas/shareable_runtime/build')); + await del(resolve(XPACK_DIR, 'plugins/canvas/shareable_runtime/build')); } async function reportTask() { @@ -50,7 +50,7 @@ async function pluginHelpersBuild() { } async function buildCanvasShareableRuntime() { - await execa(process.execPath, ['legacy/plugins/canvas/scripts/shareable_runtime'], { + await execa(process.execPath, ['plugins/canvas/scripts/shareable_runtime'], { cwd: XPACK_DIR, stdio: ['ignore', 'inherit', 'inherit'], // @ts-ignore Incorrect @types - execa supports `buffer` From e977df40ad81488e01a6f775b8e1c1fa6410942a Mon Sep 17 00:00:00 2001 From: Brent Kimmel Date: Tue, 5 May 2020 21:48:04 -0400 Subject: [PATCH 55/72] add related event generation to ancestor nodes (fixes a bug) (#64950) * add related event generation to ancestor nodes * fix tests to account for alert at n-1 --- .../endpoint/common/generate_data.test.ts | 30 ++++++++++++--- .../plugins/endpoint/common/generate_data.ts | 38 +++++++++++++++++-- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/endpoint/common/generate_data.test.ts b/x-pack/plugins/endpoint/common/generate_data.test.ts index e1a2401849301..f99fa5c871d89 100644 --- a/x-pack/plugins/endpoint/common/generate_data.test.ts +++ b/x-pack/plugins/endpoint/common/generate_data.test.ts @@ -101,20 +101,38 @@ describe('data generator', () => { }); it('with n-1 process events', () => { - for (let i = 1; i < events.length - 1; i++) { - expect(events[i].process.parent?.entity_id).toEqual(events[i - 1].process.entity_id); - expect(events[i].event.kind).toEqual('event'); - expect(events[i].event.category).toEqual('process'); + for (let i = events.length - 2; i > 0; ) { + const parentEntityIdOfChild = events[i].process.parent?.entity_id; + for ( + ; + --i >= -1 && (events[i].event.kind !== 'event' || events[i].event.category !== 'process'); + + ) { + // related event - skip it + } + expect(i).toBeGreaterThanOrEqual(0); + expect(parentEntityIdOfChild).toEqual(events[i].process.entity_id); } }); it('with a corresponding alert at the end', () => { + let previousProcessEventIndex = events.length - 2; + for ( + ; + previousProcessEventIndex >= -1 && + (events[previousProcessEventIndex].event.kind !== 'event' || + events[previousProcessEventIndex].event.category !== 'process'); + previousProcessEventIndex-- + ) { + // related event - skip it + } + expect(previousProcessEventIndex).toBeGreaterThanOrEqual(0); // The alert should be last and have the same entity_id as the previous process event expect(events[events.length - 1].process.entity_id).toEqual( - events[events.length - 2].process.entity_id + events[previousProcessEventIndex].process.entity_id ); expect(events[events.length - 1].process.parent?.entity_id).toEqual( - events[events.length - 2].process.parent?.entity_id + events[previousProcessEventIndex].process.parent?.entity_id ); expect(events[events.length - 1].event.kind).toEqual('alert'); expect(events[events.length - 1].event.category).toEqual('malware'); diff --git a/x-pack/plugins/endpoint/common/generate_data.ts b/x-pack/plugins/endpoint/common/generate_data.ts index 840574063d3f3..58393b88e37a3 100644 --- a/x-pack/plugins/endpoint/common/generate_data.ts +++ b/x-pack/plugins/endpoint/common/generate_data.ts @@ -339,13 +339,17 @@ export class EndpointDocGenerator { percentNodesWithRelated?: number, percentChildrenTerminated?: number ) { - const ancestry = this.createAlertEventAncestry(alertAncestors); + const ancestry = this.createAlertEventAncestry( + alertAncestors, + relatedEventsPerNode, + percentNodesWithRelated + ); for (let i = 0; i < ancestry.length; i++) { yield ancestry[i]; } - // ancestry will always have at least 2 elements, and the second to last element will be the process associated with the alert + // ancestry will always have at least 2 elements, and the last element will be the alert yield* this.descendantsTreeGenerator( - ancestry[ancestry.length - 2], + ancestry[ancestry.length - 1], childGenerations, maxChildrenPerNode, relatedEventsPerNode, @@ -358,18 +362,44 @@ export class EndpointDocGenerator { * Creates an alert event and associated process ancestry. The alert event will always be the last event in the return array. * @param alertAncestors - number of ancestor generations to create */ - public createAlertEventAncestry(alertAncestors = 3): Event[] { + public createAlertEventAncestry( + alertAncestors = 3, + relatedEventsPerNode = 5, + pctWithRelated = 30 + ): Event[] { const events = []; const startDate = new Date().getTime(); const root = this.generateEvent({ timestamp: startDate + 1000 }); events.push(root); let ancestor = root; + // generate related alerts for root + const processDuration: number = 6 * 3600; + if (this.randomN(100) < pctWithRelated) { + for (const relatedEvent of this.relatedEventsGenerator( + ancestor, + relatedEventsPerNode, + processDuration + )) { + events.push(relatedEvent); + } + } for (let i = 0; i < alertAncestors; i++) { ancestor = this.generateEvent({ timestamp: startDate + 1000 * (i + 1), parentEntityID: ancestor.process.entity_id, }); events.push(ancestor); + + // generate related alerts for ancestor + if (this.randomN(100) < pctWithRelated) { + for (const relatedEvent of this.relatedEventsGenerator( + ancestor, + relatedEventsPerNode, + processDuration + )) { + events.push(relatedEvent); + } + } } events.push( this.generateAlert( From 42d2443338f6c8a202435eab2bb85d1a070fc513 Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 5 May 2020 18:55:43 -0700 Subject: [PATCH 56/72] skip whole suite blocking snapshots (#65377) --- .../machine_learning/anomaly_detection/single_metric_job.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts index 913b0e71f6a3e..30327e8a422c1 100644 --- a/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/machine_learning/anomaly_detection/single_metric_job.ts @@ -71,7 +71,8 @@ export default function({ getService }: FtrProviderContext) { const calendarId = `wizard-test-calendar_${Date.now()}`; - describe('single metric', function() { + // Breaking latest ES snapshots: https://github.com/elastic/kibana/issues/65377 + describe.skip('single metric', function() { this.tags(['mlqa']); before(async () => { await esArchiver.loadIfNeeded('ml/farequote'); @@ -325,8 +326,7 @@ export default function({ getService }: FtrProviderContext) { await ml.jobWizardCommon.advanceToValidationSection(); }); - // https://github.com/elastic/kibana/issues/65377 - it.skip('job cloning displays the summary step', async () => { + it('job cloning displays the summary step', async () => { await ml.jobWizardCommon.advanceToSummarySection(); }); From edc8cb532b85d2455f5b5743e5ae02eaa47f23d4 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 5 May 2020 21:08:04 -0600 Subject: [PATCH 57/72] bug fixing (#65387) --- .../server/routes/api/cases/push_case.test.ts | 110 ++++++++++++++++++ .../case/server/routes/api/cases/push_case.ts | 6 +- 2 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/case/server/routes/api/cases/push_case.test.ts diff --git a/x-pack/plugins/case/server/routes/api/cases/push_case.test.ts b/x-pack/plugins/case/server/routes/api/cases/push_case.test.ts new file mode 100644 index 0000000000000..c68b4b0c91735 --- /dev/null +++ b/x-pack/plugins/case/server/routes/api/cases/push_case.test.ts @@ -0,0 +1,110 @@ +/* + * 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 { kibanaResponseFactory, RequestHandler } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { + createMockSavedObjectsRepository, + createRoute, + createRouteContext, + mockCases, +} from '../__fixtures__'; +import { initPushCaseUserActionApi } from './push_case'; +import { CASE_DETAILS_URL } from '../../../../common/constants'; +import { mockCaseConfigure } from '../__fixtures__/mock_saved_objects'; + +describe('Push case', () => { + let routeHandler: RequestHandler; + const mockDate = '2019-11-25T21:54:48.952Z'; + const caseExternalServiceRequestBody = { + connector_id: 'connector_id', + connector_name: 'connector_name', + external_id: 'external_id', + external_title: 'external_title', + external_url: 'external_url', + }; + beforeAll(async () => { + routeHandler = await createRoute(initPushCaseUserActionApi, 'post'); + const spyOnDate = jest.spyOn(global, 'Date') as jest.SpyInstance<{}, []>; + spyOnDate.mockImplementation(() => ({ + toISOString: jest.fn().mockReturnValue(mockDate), + })); + }); + it(`Pushes a case`, async () => { + const request = httpServerMock.createKibanaRequest({ + path: `${CASE_DETAILS_URL}/_push`, + method: 'post', + params: { + case_id: 'mock-id-3', + }, + body: caseExternalServiceRequestBody, + }); + + const theContext = createRouteContext( + createMockSavedObjectsRepository({ + caseSavedObject: mockCases, + }) + ); + + const response = await routeHandler(theContext, request, kibanaResponseFactory); + expect(response.status).toEqual(200); + expect(response.payload.external_service.pushed_at).toEqual(mockDate); + expect(response.payload.external_service.connector_id).toEqual('connector_id'); + expect(response.payload.closed_at).toEqual(null); + }); + it(`Pushes a case and closes when closure_type: 'close-by-pushing'`, async () => { + const request = httpServerMock.createKibanaRequest({ + path: `${CASE_DETAILS_URL}/_push`, + method: 'post', + params: { + case_id: 'mock-id-3', + }, + body: caseExternalServiceRequestBody, + }); + + const theContext = createRouteContext( + createMockSavedObjectsRepository({ + caseSavedObject: mockCases, + caseConfigureSavedObject: [ + { + ...mockCaseConfigure[0], + attributes: { + ...mockCaseConfigure[0].attributes, + closure_type: 'close-by-pushing', + }, + }, + ], + }) + ); + + const response = await routeHandler(theContext, request, kibanaResponseFactory); + expect(response.status).toEqual(200); + expect(response.payload.external_service.pushed_at).toEqual(mockDate); + expect(response.payload.external_service.connector_id).toEqual('connector_id'); + expect(response.payload.closed_at).toEqual(mockDate); + }); + + it(`Returns an error if pushCaseUserAction throws`, async () => { + const request = httpServerMock.createKibanaRequest({ + path: `${CASE_DETAILS_URL}/_push`, + method: 'post', + body: { + notagoodbody: 'Throw an error', + }, + }); + + const theContext = createRouteContext( + createMockSavedObjectsRepository({ + caseSavedObject: mockCases, + }) + ); + + const response = await routeHandler(theContext, request, kibanaResponseFactory); + expect(response.status).toEqual(400); + expect(response.payload.isBoom).toEqual(true); + }); +}); diff --git a/x-pack/plugins/case/server/routes/api/cases/push_case.ts b/x-pack/plugins/case/server/routes/api/cases/push_case.ts index c6638d292a197..5be36d34549b7 100644 --- a/x-pack/plugins/case/server/routes/api/cases/push_case.ts +++ b/x-pack/plugins/case/server/routes/api/cases/push_case.ts @@ -94,7 +94,8 @@ export function initPushCaseUserActionApi({ client, caseId, updatedAttributes: { - ...(myCaseConfigure.saved_objects[0].attributes.closure_type === 'close-by-pushing' + ...(myCaseConfigure.total > 0 && + myCaseConfigure.saved_objects[0].attributes.closure_type === 'close-by-pushing' ? { status: 'closed', closed_at: pushedDate, @@ -124,7 +125,8 @@ export function initPushCaseUserActionApi({ userActionService.postUserActions({ client, actions: [ - ...(myCaseConfigure.saved_objects[0].attributes.closure_type === 'close-by-pushing' + ...(myCaseConfigure.total > 0 && + myCaseConfigure.saved_objects[0].attributes.closure_type === 'close-by-pushing' ? [ buildCaseUserActionItem({ action: 'update', From 9d88805a95413c58dff2c4cdb08f4e46d0facb88 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Tue, 5 May 2020 23:12:55 -0400 Subject: [PATCH 58/72] [Ingest pipelines] Address copy feedback (#65175) --- .../public/application/app.tsx | 2 +- .../pipeline_form/pipeline_form_fields.tsx | 26 +++++--- .../pipeline_request_flyout.tsx | 2 +- .../tabs/tab_documents.tsx | 25 +++----- .../pipeline_test_flyout/tabs/tab_output.tsx | 63 +++++++++--------- .../components/pipeline_form/schema.tsx | 10 +-- .../pipelines_list/details_flyout.tsx | 4 +- .../sections/pipelines_list/empty_list.tsx | 64 +++++++++++++------ .../sections/pipelines_list/main.tsx | 29 ++++++--- 9 files changed, 129 insertions(+), 96 deletions(-) diff --git a/x-pack/plugins/ingest_pipelines/public/application/app.tsx b/x-pack/plugins/ingest_pipelines/public/application/app.tsx index ba7675b507596..98b49bafd6ed6 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/app.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/app.tsx @@ -71,7 +71,7 @@ export const App: FunctionComponent = () => { title={ } message={ diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx index 045afd52204fa..b90683426887f 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx @@ -95,7 +95,7 @@ export const PipelineFormFields: React.FunctionComponent = ({ description={ } > @@ -122,12 +122,16 @@ export const PipelineFormFields: React.FunctionComponent = ({ <> + {i18n.translate('xpack.ingestPipelines.form.processorsDocumentionLink', { - defaultMessage: 'Learn more.', + defaultMessage: 'Learn more', })} ), @@ -172,12 +176,16 @@ export const PipelineFormFields: React.FunctionComponent = ({ <> + {i18n.translate('xpack.ingestPipelines.form.onFailureDocumentionLink', { - defaultMessage: 'Learn more.', + defaultMessage: 'Learn more', })} ), @@ -188,7 +196,7 @@ export const PipelineFormFields: React.FunctionComponent = ({ label={ } checked={isOnFailureEditorVisible} @@ -207,7 +215,7 @@ export const PipelineFormFields: React.FunctionComponent = ({ euiCodeEditorProps: { height: '300px', 'aria-label': i18n.translate('xpack.ingestPipelines.form.onFailureFieldAriaLabel', { - defaultMessage: 'On-failure processors JSON editor', + defaultMessage: 'Failure processors JSON editor', }), }, }} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_request_flyout/pipeline_request_flyout.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_request_flyout/pipeline_request_flyout.tsx index 58e86695808b1..7cfe887d68d52 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_request_flyout/pipeline_request_flyout.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_request_flyout/pipeline_request_flyout.tsx @@ -65,7 +65,7 @@ export const PipelineRequestFlyout: React.FunctionComponent = ({

diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_documents.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_documents.tsx index 97bf03dbdc068..4b5ed7d115a51 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_documents.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_documents.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { EuiSpacer, EuiText, EuiButton, EuiHorizontalRule, EuiLink } from '@elastic/eui'; +import { EuiSpacer, EuiText, EuiButton, EuiLink } from '@elastic/eui'; import { getUseField, @@ -72,14 +72,18 @@ export const DocumentsTab: React.FunctionComponent = ({

+ {i18n.translate( 'xpack.ingestPipelines.testPipelineFlyout.documentsTab.simulateDocumentionLink', { - defaultMessage: 'Learn more.', + defaultMessage: 'Learn more', } )} @@ -115,17 +119,6 @@ export const DocumentsTab: React.FunctionComponent = ({ }} /> - - - -

- -

- - = ({ ) : ( )} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_output.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_output.tsx index aa80f8c86ad8b..bcaf186e62129 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_output.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_test_flyout/tabs/tab_output.tsx @@ -11,10 +11,10 @@ import { EuiSpacer, EuiText, EuiSwitch, - EuiLink, - EuiIcon, + EuiButton, EuiLoadingSpinner, - EuiIconTip, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { useTestConfigContext } from '../../test_config_context'; @@ -59,44 +59,39 @@ export const OutputTab: React.FunctionComponent = ({

handleExecute(cachedDocuments!, cachedVerbose)}> - {' '} - - - ), - }} + defaultMessage="View the output data, or see how each processor affects the document as it passes through the pipeline." />

- + - + + + + } + checked={cachedVerbose} + onChange={e => onEnableVerbose(e.target.checked)} + /> + + + handleExecute(cachedDocuments!, cachedVerbose)} + iconType="refresh" + > {' '} - - } + id="xpack.ingestPipelines.testPipelineFlyout.outputTab.descriptionLinkLabel" + defaultMessage="Refresh output" /> - - } - checked={cachedVerbose} - onChange={e => onEnableVerbose(e.target.checked)} - /> + + + diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx index 2e2689f41527a..f222d48c11af0 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx @@ -25,7 +25,7 @@ export const pipelineFormSchema: FormSchema = { { validator: emptyField( i18n.translate('xpack.ingestPipelines.form.pipelineNameRequiredError', { - defaultMessage: 'A pipeline name is required.', + defaultMessage: 'Name is required.', }) ), }, @@ -40,7 +40,7 @@ export const pipelineFormSchema: FormSchema = { { validator: emptyField( i18n.translate('xpack.ingestPipelines.form.pipelineDescriptionRequiredError', { - defaultMessage: 'A pipeline description is required.', + defaultMessage: 'A description is required.', }) ), }, @@ -83,7 +83,7 @@ export const pipelineFormSchema: FormSchema = { { validator: isJsonField( i18n.translate('xpack.ingestPipelines.form.processorsJsonError', { - defaultMessage: 'The processors JSON is not valid.', + defaultMessage: 'The input is not valid.', }) ), }, @@ -91,7 +91,7 @@ export const pipelineFormSchema: FormSchema = { }, on_failure: { label: i18n.translate('xpack.ingestPipelines.form.onFailureFieldLabel', { - defaultMessage: 'On-failure processors (optional)', + defaultMessage: 'Failure processors (optional)', }), helpText: ( = ({ {/* Processors JSON */} {i18n.translate('xpack.ingestPipelines.list.pipelineDetails.processorsTitle', { - defaultMessage: 'Processors JSON', + defaultMessage: 'Processors', })} @@ -156,7 +156,7 @@ export const PipelineDetailsFlyout: FunctionComponent = ({ {i18n.translate( 'xpack.ingestPipelines.list.pipelineDetails.failureProcessorsTitle', { - defaultMessage: 'On failure processors JSON', + defaultMessage: 'Failure processors', } )} diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx index ef64fb33a6a55..318a9219b2010 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/empty_list.tsx @@ -5,25 +5,49 @@ */ import React, { FunctionComponent } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiButton, EuiEmptyPrompt, EuiLink, EuiPageBody, EuiPageContent } from '@elastic/eui'; import { BASE_PATH } from '../../../../common/constants'; +import { useKibana } from '../../../shared_imports'; -export const EmptyList: FunctionComponent = () => ( - - {i18n.translate('xpack.ingestPipelines.list.table.emptyPromptTitle', { - defaultMessage: 'Start by creating a pipeline', - })} - - } - actions={ - - {i18n.translate('xpack.ingestPipelines.list.table.emptyPrompt.createButtonLabel', { - defaultMessage: 'Create a pipeline', - })} - - } - /> -); +export const EmptyList: FunctionComponent = () => { + const { services } = useKibana(); + + return ( + + + + {i18n.translate('xpack.ingestPipelines.list.table.emptyPromptTitle', { + defaultMessage: 'Start by creating a pipeline', + })} + + } + body={ +

+ +
+ + {i18n.translate('xpack.ingestPipelines.list.table.emptyPromptDocumentionLink', { + defaultMessage: 'Learn more', + })} + +

+ } + actions={ + + {i18n.translate('xpack.ingestPipelines.list.table.emptyPrompt.createButtonLabel', { + defaultMessage: 'Create a pipeline', + })} + + } + /> +
+
+ ); +}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx index 0d38905c0fb49..23d105c807c8b 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/main.tsx @@ -6,7 +6,6 @@ import React, { useEffect, useState } from 'react'; import { RouteComponentProps } from 'react-router-dom'; -import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { Location } from 'history'; import { parse } from 'query-string'; @@ -19,10 +18,11 @@ import { EuiFlexItem, EuiButtonEmpty, EuiCallOut, + EuiLink, + EuiSpacer, + EuiText, } from '@elastic/eui'; -import { EuiSpacer, EuiText } from '@elastic/eui'; - import { Pipeline } from '../../../../common/types'; import { BASE_PATH } from '../../../../common/constants'; import { useKibana, SectionLoading } from '../../../shared_imports'; @@ -102,7 +102,7 @@ export const PipelinesList: React.FunctionComponent = ({ /> ); } else { - content = ; + return ; } const renderFlyout = (): React.ReactNode => { @@ -162,7 +162,7 @@ export const PipelinesList: React.FunctionComponent = ({ @@ -172,9 +172,22 @@ export const PipelinesList: React.FunctionComponent = ({ + + + ), + }} + /> + } /> ) : ( content From 35e10273d3c89c7ced66306d7655204278c95216 Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 5 May 2020 23:14:14 -0500 Subject: [PATCH 59/72] New nav (#64018) Notably, also removes aria-hidden from many visualizations --- ...ibana-plugin-core-public.appcategory.id.md | 13 + .../kibana-plugin-core-public.appcategory.md | 1 + ...gin-core-public.chromestart.getnavtype_.md | 17 + .../kibana-plugin-core-public.chromestart.md | 1 + .../core/public/kibana-plugin-core-public.md | 1 + .../kibana-plugin-core-public.navtype.md | 11 + docs/management/advanced-options.asciidoc | 3 + package.json | 2 +- packages/kbn-ui-shared-deps/package.json | 2 +- src/core/public/chrome/chrome_service.mock.ts | 5 +- src/core/public/chrome/chrome_service.test.ts | 11 +- src/core/public/chrome/chrome_service.tsx | 41 +- src/core/public/chrome/index.ts | 1 + .../collapsible_nav.test.tsx.snap | 4506 +++++++++++++++++ src/core/public/chrome/ui/header/_index.scss | 36 +- .../chrome/ui/header/collapsible_nav.test.tsx | 136 + .../chrome/ui/header/collapsible_nav.tsx | 281 + src/core/public/chrome/ui/header/header.tsx | 101 +- src/core/public/chrome/ui/header/index.ts | 2 +- .../public/chrome/ui/header/nav_drawer.tsx | 16 +- src/core/public/chrome/ui/header/nav_link.tsx | 108 +- .../public/chrome/ui/header/recent_links.tsx | 70 +- src/core/public/chrome/ui/header/types.ts | 21 + src/core/public/chrome/ui/index.ts | 1 + src/core/public/core_system.ts | 1 + src/core/public/index.ts | 2 + .../flyout_service.test.tsx.snap | 19 +- src/core/public/public.api.md | 16 +- src/core/public/rendering/_base.scss | 49 +- .../legacy/plugins/get_nav_links.test.ts | 4 + src/core/server/server.api.md | 9 +- src/core/types/app_category.ts | 5 + src/core/utils/default_app_categories.ts | 13 +- src/legacy/core_plugins/kibana/index.js | 14 +- .../kibana/public/management/index.js | 2 +- .../kibana/server/ui_setting_defaults.js | 20 + src/legacy/core_plugins/timelion/index.ts | 4 +- .../label_template_flyout.test.tsx.snap | 5 - .../url_template_flyout.test.tsx.snap | 5 - .../__snapshots__/help_flyout.test.tsx.snap | 10 - .../ui/public/management/breadcrumbs.ts | 2 +- .../ui/public/styles/_legacy/_base.scss | 12 +- .../management_app/components/form/_form.scss | 2 + .../management_app/components/form/form.tsx | 17 +- .../public/application/_dashboard_app.scss | 3 +- .../filter_editor/phrase_suggestor.tsx | 4 +- .../saved_query_management_component.tsx | 1 + .../open_search_panel.test.js.snap | 4 - .../components/panel_options_menu/index.tsx | 4 +- .../__snapshots__/list_control.test.tsx.snap | 1 + .../public/components/vis/list_control.tsx | 4 + .../validated_range/validated_dual_range.tsx | 63 +- .../public/legacy/sections_register.js | 2 +- .../management/public/management_app.tsx | 2 +- src/plugins/management/public/plugin.ts | 4 +- .../__snapshots__/flyout.test.tsx.snap | 12 - .../__snapshots__/relationships.test.tsx.snap | 25 - .../opt_in_example_flyout.test.tsx.snap | 3 - .../public/actions/action_internal.ts | 2 + .../visualization_noresults.test.js.snap | 1 - .../visualization_requesterror.test.js.snap | 1 - .../components/visualization_chart.test.js | 2 +- .../public/components/visualization_chart.tsx | 9 +- .../components/visualization_noresults.tsx | 2 +- .../components/visualization_requesterror.tsx | 2 +- .../__snapshots__/new_vis_modal.test.tsx.snap | 30 - .../wizard/type_selection/vis_type_icon.tsx | 12 +- test/accessibility/apps/dashboard.ts | 6 - .../apps/dashboard/dashboard_time.js | 4 +- test/functional/apps/discover/_discover.js | 6 +- test/functional/apps/visualize/_tile_map.js | 41 +- test/functional/page_objects/header_page.ts | 8 +- test/functional/services/apps_menu.ts | 52 +- .../plugins/kbn_tp_run_pipeline/package.json | 2 +- .../kbn_sample_panel_action/package.json | 2 +- .../kbn_tp_custom_visualizations/package.json | 2 +- .../kbn_tp_embeddable_explorer/package.json | 2 +- .../core_plugins/application_leave_confirm.ts | 8 +- .../core_plugins/application_status.ts | 8 - .../test_suites/core_plugins/applications.ts | 24 +- x-pack/legacy/plugins/dashboard_mode/index.js | 4 +- x-pack/legacy/plugins/maps/index.js | 3 +- x-pack/package.json | 2 +- .../components/fullscreen/fullscreen.scss | 2 + x-pack/plugins/canvas/public/plugin.tsx | 2 +- .../flyout_frame/flyout_frame.story.tsx | 2 +- x-pack/plugins/graph/public/plugin.ts | 4 +- x-pack/plugins/infra/public/plugin.ts | 4 +- x-pack/plugins/maps/public/_main.scss | 2 +- .../rule_editor_flyout.test.js.snap | 20 - x-pack/plugins/ml/public/plugin.ts | 4 +- .../alerts/__snapshots__/status.test.tsx.snap | 5 - .../__snapshots__/detail_drawer.test.js.snap | 20 - .../flyout/__snapshots__/flyout.test.js.snap | 25 - .../public/application/components/main.tsx | 13 +- .../application/components/main_controls.tsx | 18 +- .../painless_lab/public/styles/_index.scss | 2 +- .../report_info_button.test.tsx.snap | 210 +- .../rule_editor_panel/field_rule_editor.tsx | 2 +- .../nav_control_component.test.tsx | 8 +- x-pack/plugins/siem/public/plugin.tsx | 2 + .../nav_control_popover.test.tsx.snap | 4 +- .../translations/translations/ja-JP.json | 12 - .../translations/translations/zh-CN.json | 12 - x-pack/plugins/uptime/public/apps/plugin.ts | 7 +- .../__snapshots__/ml_flyout.test.tsx.snap | 6 +- .../advanced_settings_security.ts | 6 +- .../advanced_settings_spaces.ts | 2 +- .../apps/apm/feature_controls/apm_security.ts | 4 +- .../feature_controls/canvas_security.ts | 4 +- .../feature_controls/dashboard_security.ts | 6 +- .../dashboard_mode/dashboard_view_mode.js | 4 +- .../feature_controls/dev_tools_security.ts | 4 +- .../feature_controls/discover_security.ts | 6 +- .../graph/feature_controls/graph_security.ts | 4 +- .../index_patterns_security.ts | 6 +- .../feature_controls/index_patterns_spaces.ts | 2 +- .../infrastructure_security.ts | 4 +- .../infra/feature_controls/logs_security.ts | 4 +- .../maps/feature_controls/maps_security.ts | 6 +- .../feature_controls/spaces_security.ts | 4 +- .../feature_controls/timelion_security.ts | 4 +- .../feature_controls/uptime_security.ts | 4 +- .../feature_controls/visualize_security.ts | 6 +- yarn.lock | 8 +- 125 files changed, 5748 insertions(+), 691 deletions(-) create mode 100644 docs/development/core/public/kibana-plugin-core-public.appcategory.id.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md create mode 100644 docs/development/core/public/kibana-plugin-core-public.navtype.md create mode 100644 src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap create mode 100644 src/core/public/chrome/ui/header/collapsible_nav.test.tsx create mode 100644 src/core/public/chrome/ui/header/collapsible_nav.tsx create mode 100644 src/core/public/chrome/ui/header/types.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.appcategory.id.md b/docs/development/core/public/kibana-plugin-core-public.appcategory.id.md new file mode 100644 index 0000000000000..0342a1d9ee95b --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.appcategory.id.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [AppCategory](./kibana-plugin-core-public.appcategory.md) > [id](./kibana-plugin-core-public.appcategory.id.md) + +## AppCategory.id property + +Unique identifier for the categories + +Signature: + +```typescript +id: string; +``` diff --git a/docs/development/core/public/kibana-plugin-core-public.appcategory.md b/docs/development/core/public/kibana-plugin-core-public.appcategory.md index b115baa1be1a3..d91727a1bbf29 100644 --- a/docs/development/core/public/kibana-plugin-core-public.appcategory.md +++ b/docs/development/core/public/kibana-plugin-core-public.appcategory.md @@ -18,6 +18,7 @@ export interface AppCategory | --- | --- | --- | | [ariaLabel](./kibana-plugin-core-public.appcategory.arialabel.md) | string | If the visual label isn't appropriate for screen readers, can override it here | | [euiIconType](./kibana-plugin-core-public.appcategory.euiicontype.md) | string | Define an icon to be used for the category If the category is only 1 item, and no icon is defined, will default to the product icon Defaults to initials if no icon is defined | +| [id](./kibana-plugin-core-public.appcategory.id.md) | string | Unique identifier for the categories | | [label](./kibana-plugin-core-public.appcategory.label.md) | string | Label used for cateogry name. Also used as aria-label if one isn't set. | | [order](./kibana-plugin-core-public.appcategory.order.md) | number | The order that categories will be sorted in Prefer large steps between categories to allow for further editing (Default categories are in steps of 1000) | diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md new file mode 100644 index 0000000000000..09864be43996d --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.chromestart.getnavtype_.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeStart](./kibana-plugin-core-public.chromestart.md) > [getNavType$](./kibana-plugin-core-public.chromestart.getnavtype_.md) + +## ChromeStart.getNavType$() method + +Get the navigation type TODO \#64541 Can delete + +Signature: + +```typescript +getNavType$(): Observable; +``` +Returns: + +`Observable` + diff --git a/docs/development/core/public/kibana-plugin-core-public.chromestart.md b/docs/development/core/public/kibana-plugin-core-public.chromestart.md index c179e089d7cfd..b4eadc93fe78d 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromestart.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromestart.md @@ -58,6 +58,7 @@ core.chrome.setHelpExtension(elem => { | [getHelpExtension$()](./kibana-plugin-core-public.chromestart.gethelpextension_.md) | Get an observable of the current custom help conttent | | [getIsNavDrawerLocked$()](./kibana-plugin-core-public.chromestart.getisnavdrawerlocked_.md) | Get an observable of the current locked state of the nav drawer. | | [getIsVisible$()](./kibana-plugin-core-public.chromestart.getisvisible_.md) | Get an observable of the current visibility state of the chrome. | +| [getNavType$()](./kibana-plugin-core-public.chromestart.getnavtype_.md) | Get the navigation type TODO \#64541 Can delete | | [removeApplicationClass(className)](./kibana-plugin-core-public.chromestart.removeapplicationclass.md) | Remove a className added with addApplicationClass(). If className is unknown it is ignored. | | [setAppTitle(appTitle)](./kibana-plugin-core-public.chromestart.setapptitle.md) | Sets the current app's title | | [setBadge(badge)](./kibana-plugin-core-public.chromestart.setbadge.md) | Override the current badge | diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index c24e4cf908b87..eafc81447ee03 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -158,6 +158,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [IContextProvider](./kibana-plugin-core-public.icontextprovider.md) | A function that returns a context value for a specific key of given context type. | | [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | | [MountPoint](./kibana-plugin-core-public.mountpoint.md) | A function that should mount DOM content inside the provided container element and return a handler to unmount it. | +| [NavType](./kibana-plugin-core-public.navtype.md) | | | [PluginInitializer](./kibana-plugin-core-public.plugininitializer.md) | The plugin export at the root of a plugin's public directory should conform to this interface. | | [PluginOpaqueId](./kibana-plugin-core-public.pluginopaqueid.md) | | | [PublicUiSettingsParams](./kibana-plugin-core-public.publicuisettingsparams.md) | A sub-set of [UiSettingsParams](./kibana-plugin-core-public.uisettingsparams.md) exposed to the client-side. | diff --git a/docs/development/core/public/kibana-plugin-core-public.navtype.md b/docs/development/core/public/kibana-plugin-core-public.navtype.md new file mode 100644 index 0000000000000..8f1d9a4351754 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-core-public.navtype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [NavType](./kibana-plugin-core-public.navtype.md) + +## NavType type + +Signature: + +```typescript +export declare type NavType = 'modern' | 'legacy'; +``` diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 51910169e8673..cafd50d92376f 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -68,6 +68,9 @@ into the document when displaying it. `metrics:max_buckets`:: The maximum numbers of buckets that a single data source can return. This might arise when the user selects a short interval (for example, 1s) for a long time period (1 year). +`pageNavigation`:: The style of navigation menu for Kibana. +Choices are Legacy, the legacy style where every plugin is represented in the nav, +and Modern, a new format that bundles related plugins together in flyaway nested navigation. `query:allowLeadingWildcards`:: Allows a wildcard (*) as the first character in a query clause. Only applies when experimental query features are enabled in the query bar. To disallow leading wildcards in Lucene queries, diff --git a/package.json b/package.json index 178ccbac7d420..8a92b46489308 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "@elastic/charts": "19.2.0", "@elastic/datemath": "5.0.3", "@elastic/ems-client": "7.8.0", - "@elastic/eui": "22.3.0", + "@elastic/eui": "22.3.1", "@elastic/filesaver": "1.1.2", "@elastic/good": "8.1.1-kibana2", "@elastic/numeral": "2.4.0", diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index ae883a5032fe7..8259f251a9be3 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@elastic/charts": "19.2.0", - "@elastic/eui": "22.3.0", + "@elastic/eui": "22.3.1", "@kbn/i18n": "1.0.0", "abortcontroller-polyfill": "^1.4.0", "angular": "^1.7.9", diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index 89007461b63e6..4a79dd8869c1c 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -23,7 +23,8 @@ import { ChromeBreadcrumb, ChromeService, InternalChromeStart, -} from './chrome_service'; + NavType, +} from './'; const createStartContractMock = () => { const startContract: DeeplyMockedKeys = { @@ -72,6 +73,7 @@ const createStartContractMock = () => { setHelpExtension: jest.fn(), setHelpSupportUrl: jest.fn(), getIsNavDrawerLocked$: jest.fn(), + getNavType$: jest.fn(), }; startContract.navLinks.getAll.mockReturnValue([]); startContract.getBrand$.mockReturnValue(new BehaviorSubject({} as ChromeBrand)); @@ -81,6 +83,7 @@ const createStartContractMock = () => { startContract.getBreadcrumbs$.mockReturnValue(new BehaviorSubject([{} as ChromeBreadcrumb])); startContract.getHelpExtension$.mockReturnValue(new BehaviorSubject(undefined)); startContract.getIsNavDrawerLocked$.mockReturnValue(new BehaviorSubject(false)); + startContract.getNavType$.mockReturnValue(new BehaviorSubject('modern' as NavType)); return startContract; }; diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index a765ed47ea712..327be61cc63e3 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -17,18 +17,18 @@ * under the License. */ -import * as Rx from 'rxjs'; -import { take, toArray } from 'rxjs/operators'; import { shallow } from 'enzyme'; import React from 'react'; - +import * as Rx from 'rxjs'; +import { take, toArray } from 'rxjs/operators'; +import { App } from '../application'; import { applicationServiceMock } from '../application/application_service.mock'; +import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; import { httpServiceMock } from '../http/http_service.mock'; import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock'; import { notificationServiceMock } from '../notifications/notifications_service.mock'; -import { docLinksServiceMock } from '../doc_links/doc_links_service.mock'; +import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; import { ChromeService } from './chrome_service'; -import { App } from '../application'; class FakeApp implements App { public title = `${this.id} App`; @@ -51,6 +51,7 @@ function defaultStartDeps(availableApps?: App[]) { http: httpServiceMock.createStartContract(), injectedMetadata: injectedMetadataServiceMock.createStartContract(), notifications: notificationServiceMock.createStartContract(), + uiSettings: uiSettingsServiceMock.createStartContract(), }; if (availableApps) { diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 3d9eeff09ecce..3fc22caaefb04 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -17,27 +17,26 @@ * under the License. */ +import { Breadcrumb as EuiBreadcrumb, IconType } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import React from 'react'; -import { BehaviorSubject, Observable, ReplaySubject, combineLatest, of, merge } from 'rxjs'; +import { BehaviorSubject, combineLatest, merge, Observable, of, ReplaySubject } from 'rxjs'; import { flatMap, map, takeUntil } from 'rxjs/operators'; import { parse } from 'url'; - -import { i18n } from '@kbn/i18n'; -import { IconType, Breadcrumb as EuiBreadcrumb } from '@elastic/eui'; - -import { InjectedMetadataStart } from '../injected_metadata'; -import { NotificationsStart } from '../notifications'; import { InternalApplicationStart } from '../application'; +import { DocLinksStart } from '../doc_links'; import { HttpStart } from '../http'; - +import { InjectedMetadataStart } from '../injected_metadata'; +import { NotificationsStart } from '../notifications'; +import { IUiSettingsClient } from '../ui_settings'; +import { KIBANA_ASK_ELASTIC_LINK } from './constants'; +import { ChromeDocTitle, DocTitleService } from './doc_title'; +import { ChromeNavControls, NavControlsService } from './nav_controls'; import { ChromeNavLinks, NavLinksService } from './nav_links'; import { ChromeRecentlyAccessed, RecentlyAccessedService } from './recently_accessed'; -import { NavControlsService, ChromeNavControls } from './nav_controls'; -import { DocTitleService, ChromeDocTitle } from './doc_title'; -import { LoadingIndicator, Header } from './ui'; -import { DocLinksStart } from '../doc_links'; +import { Header, LoadingIndicator } from './ui'; +import { NavType } from './ui/header'; import { ChromeHelpExtensionMenuLink } from './ui/header/header_help_menu'; -import { KIBANA_ASK_ELASTIC_LINK } from './constants'; export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle }; const IS_LOCKED_KEY = 'core.chrome.isLocked'; @@ -84,6 +83,7 @@ interface StartDeps { http: HttpStart; injectedMetadata: InjectedMetadataStart; notifications: NotificationsStart; + uiSettings: IUiSettingsClient; } /** @internal */ @@ -136,6 +136,7 @@ export class ChromeService { http, injectedMetadata, notifications, + uiSettings, }: StartDeps): Promise { this.initVisibility(application); @@ -160,6 +161,10 @@ export class ChromeService { const getIsNavDrawerLocked$ = isNavDrawerLocked$.pipe(takeUntil(this.stop$)); + // TODO #64541 + // Can delete + const getNavType$ = uiSettings.get$('pageNavigation').pipe(takeUntil(this.stop$)); + if (!this.params.browserSupportsCsp && injectedMetadata.getCspConfig().warnLegacyBrowsers) { notifications.toasts.addWarning( i18n.translate('core.chrome.legacyBrowserWarning', { @@ -197,6 +202,7 @@ export class ChromeService { navControlsRight$={navControls.getRight$()} onIsLockedUpdate={setIsNavDrawerLocked} isLocked$={getIsNavDrawerLocked$} + navType$={getNavType$} /> ), @@ -257,6 +263,8 @@ export class ChromeService { setHelpSupportUrl: (url: string) => helpSupportUrl$.next(url), getIsNavDrawerLocked$: () => getIsNavDrawerLocked$, + + getNavType$: () => getNavType$, }; } @@ -403,6 +411,13 @@ export interface ChromeStart { * Get an observable of the current locked state of the nav drawer. */ getIsNavDrawerLocked$(): Observable; + + /** + * Get the navigation type + * TODO #64541 + * Can delete + */ + getNavType$(): Observable; } /** @internal */ diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 4a500836990a7..cc1e0851f5944 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -33,6 +33,7 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, } from './ui/header/header_help_menu'; +export { NavType } from './ui'; export { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; export { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem } from './recently_accessed'; export { ChromeNavControl, ChromeNavControls } from './nav_controls'; diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap new file mode 100644 index 0000000000000..14d5b2e8fdcbb --- /dev/null +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -0,0 +1,4506 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CollapsibleNav renders links grouped by category 1`] = ` + + + + + + } + /> + + + + +
+ +
+
+
+ + +
+ } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + > + + +
+ } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + /> + + +
+
+ +
+ + + + + +`; + +exports[`CollapsibleNav renders the default nav 1`] = ` + + + +`; + +exports[`CollapsibleNav renders the default nav 2`] = ` + + + + + + } + /> + + + + +
+ +
+
+
+ + + + +
+
+ +
+ + + + + +`; + +exports[`CollapsibleNav renders the default nav 3`] = ` + + + + + + +
+ +
+
+
+ + +
+ } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + > + + +
+ } + onActivation={[Function]} + onDeactivation={[Function]} + persistentFocus={false} + /> + + +
+
+ +
+ + + + + +`; diff --git a/src/core/public/chrome/ui/header/_index.scss b/src/core/public/chrome/ui/header/_index.scss index f19728a52dd70..5c5e7f18b60a4 100644 --- a/src/core/public/chrome/ui/header/_index.scss +++ b/src/core/public/chrome/ui/header/_index.scss @@ -1,25 +1,12 @@ -@import '@elastic/eui/src/components/header/variables'; -@import '@elastic/eui/src/components/nav_drawer/variables'; - -.chrHeaderWrapper { +// TODO #64541 +// Delete this block +.chrHeaderWrapper:not(.headerWrapper) { width: 100%; position: fixed; top: 0; z-index: 10; } -.chrHeaderWrapper ~ .app-wrapper:not(.hidden-chrome) { - top: $euiHeaderChildSize; - left: $euiHeaderChildSize; - - // HOTFIX: Temporary fix for flyouts not inside portals - // SASSTODO: Find an actual solution - .euiFlyout { - top: $euiHeaderChildSize; - height: calc(100% - #{$euiHeaderChildSize}); - } -} - .chrHeaderHelpMenu__version { text-transform: none; } @@ -29,19 +16,8 @@ margin-right: $euiSize; } -// Mobile header is smaller -@include euiBreakpoint('xs', 's') { - .chrHeaderWrapper ~ .app-wrapper:not(.hidden-chrome) { - left: 0; - } -} - -@include euiBreakpoint('xl') { - .chrHeaderWrapper--navIsLocked { - ~ .app-wrapper:not(.hidden-chrome) { - // Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS) - left: $euiNavDrawerWidthExpanded !important; // sass-lint:disable-line no-important - transition: left $euiAnimSpeedFast $euiAnimSlightResistance; - } +.header__toggleNavButtonSection { + .euiBody--collapsibleNavIsDocked & { + display: none; } } diff --git a/src/core/public/chrome/ui/header/collapsible_nav.test.tsx b/src/core/public/chrome/ui/header/collapsible_nav.test.tsx new file mode 100644 index 0000000000000..4a9d3071b93be --- /dev/null +++ b/src/core/public/chrome/ui/header/collapsible_nav.test.tsx @@ -0,0 +1,136 @@ +/* + * 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 { mount, ReactWrapper } from 'enzyme'; +import React from 'react'; +import sinon from 'sinon'; +import { CollapsibleNav } from './collapsible_nav'; +import { AppCategory } from '../../../../types'; +import { DEFAULT_APP_CATEGORIES } from '../../..'; +import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; + +jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => ({ + htmlIdGenerator: () => () => 'mockId', +})); + +const { kibana, observability, security, management } = DEFAULT_APP_CATEGORIES; + +function mockLink(label: string, category?: AppCategory) { + return { + key: label, + label, + href: label, + isActive: true, + onClick: () => {}, + category, + 'data-test-subj': label, + }; +} + +function mockRecentNavLink(label: string) { + return { + href: label, + label, + title: label, + 'aria-label': label, + }; +} + +function mockProps() { + return { + id: 'collapsible-nav', + homeHref: '/', + isLocked: false, + isOpen: false, + navLinks: [], + recentNavLinks: [], + storage: new StubBrowserStorage(), + onIsOpenUpdate: () => {}, + onIsLockedUpdate: () => {}, + }; +} + +describe('CollapsibleNav', () => { + // this test is mostly an "EUI works as expected" sanity check + it('renders the default nav', () => { + const onLock = sinon.spy(); + const component = mount(); + expect(component).toMatchSnapshot(); + + component.setProps({ isOpen: true }); + expect(component).toMatchSnapshot(); + + component.setProps({ isLocked: true }); + expect(component).toMatchSnapshot(); + + // limit the find to buttons because jest also renders data-test-subj on a JSX wrapper element + component.find('button[data-test-subj="collapsible-nav-lock"]').simulate('click'); + expect(onLock.callCount).toEqual(1); + }); + + it('renders links grouped by category', () => { + // just a test of category functionality, categories are not accurate + const navLinks = [ + mockLink('discover', kibana), + mockLink('siem', security), + mockLink('metrics', observability), + mockLink('monitoring', management), + mockLink('visualize', kibana), + mockLink('dashboard', kibana), + mockLink('canvas'), // links should be able to be rendered top level as well + mockLink('logs', observability), + ]; + const recentNavLinks = [mockRecentNavLink('recent 1'), mockRecentNavLink('recent 2')]; + const component = mount( + + ); + expect(component).toMatchSnapshot(); + }); + + it('remembers collapsible section state', () => { + function expectNavLinksCount(component: ReactWrapper, count: number) { + expect( + component.find('.euiAccordion-isOpen a[data-test-subj="collapsibleNavAppLink"]').length + ).toEqual(count); + } + + const navLinks = [ + mockLink('discover', kibana), + mockLink('siem', security), + mockLink('metrics', observability), + mockLink('monitoring', management), + mockLink('visualize', kibana), + mockLink('dashboard', kibana), + mockLink('logs', observability), + ]; + const component = mount(); + expectNavLinksCount(component, 7); + component.find('[data-test-subj="collapsibleNavGroup-kibana"] button').simulate('click'); + expectNavLinksCount(component, 4); + component.setProps({ isOpen: false }); + expectNavLinksCount(component, 0); // double check the nav closed + component.setProps({ isOpen: true }); + expectNavLinksCount(component, 4); + }); +}); diff --git a/src/core/public/chrome/ui/header/collapsible_nav.tsx b/src/core/public/chrome/ui/header/collapsible_nav.tsx new file mode 100644 index 0000000000000..274195f1917a5 --- /dev/null +++ b/src/core/public/chrome/ui/header/collapsible_nav.tsx @@ -0,0 +1,281 @@ +/* + * 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 { + EuiCollapsibleNav, + EuiCollapsibleNavGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiListGroup, + EuiListGroupItem, + EuiShowFor, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { groupBy, sortBy } from 'lodash'; +import React, { useRef } from 'react'; +import { AppCategory } from '../../../../types'; +import { OnIsLockedUpdate } from './'; +import { NavLink, RecentNavLink } from './nav_link'; + +function getAllCategories(allCategorizedLinks: Record) { + const allCategories = {} as Record; + + for (const [key, value] of Object.entries(allCategorizedLinks)) { + allCategories[key] = value[0].category; + } + + return allCategories; +} + +function getOrderedCategories( + mainCategories: Record, + categoryDictionary: ReturnType +) { + return sortBy( + Object.keys(mainCategories), + categoryName => categoryDictionary[categoryName]?.order + ); +} + +function getCategoryLocalStorageKey(id: string) { + return `core.navGroup.${id}`; +} + +function getIsCategoryOpen(id: string, storage: Storage) { + const value = storage.getItem(getCategoryLocalStorageKey(id)) ?? 'true'; + + return value === 'true'; +} + +function setIsCategoryOpen(id: string, isOpen: boolean, storage: Storage) { + storage.setItem(getCategoryLocalStorageKey(id), `${isOpen}`); +} + +interface Props { + isLocked: boolean; + isOpen: boolean; + navLinks: NavLink[]; + recentNavLinks: RecentNavLink[]; + homeHref: string; + id: string; + storage?: Storage; + onIsLockedUpdate: OnIsLockedUpdate; + onIsOpenUpdate: (isOpen?: boolean) => void; +} + +export function CollapsibleNav({ + isLocked, + isOpen, + navLinks, + recentNavLinks, + onIsLockedUpdate, + onIsOpenUpdate, + homeHref, + id, + storage = window.localStorage, +}: Props) { + const lockRef = useRef(null); + const groupedNavLinks = groupBy(navLinks, link => link?.category?.id); + const { undefined: unknowns = [], ...allCategorizedLinks } = groupedNavLinks; + const categoryDictionary = getAllCategories(allCategorizedLinks); + const orderedCategories = getOrderedCategories(allCategorizedLinks, categoryDictionary); + + return ( + + {/* Pinned items */} + + + onIsOpenUpdate(false), + }, + ]} + maxWidth="none" + color="text" + gutterSize="none" + size="s" + /> + + + + + + + {/* Recently viewed */} + setIsCategoryOpen('recentlyViewed', isCategoryOpen, storage)} + > + {recentNavLinks.length > 0 ? ( + { + // TODO #64541 + // Can remove icon from recent links completely + const { iconType, ...linkWithoutIcon } = link; + return linkWithoutIcon; + })} + maxWidth="none" + color="subdued" + gutterSize="none" + size="s" + /> + ) : ( + +

+ {i18n.translate('core.ui.EmptyRecentlyViewed', { + defaultMessage: 'No recently viewed items', + })} +

+
+ )} +
+ + {/* Kibana, Observability, Security, and Management sections */} + {orderedCategories.map((categoryName, i) => { + const category = categoryDictionary[categoryName]!; + const links = allCategorizedLinks[categoryName].map( + ({ label, href, isActive, isDisabled, onClick }: NavLink) => ({ + label, + href, + isActive, + isDisabled, + 'data-test-subj': 'collapsibleNavAppLink', + onClick: (e: React.MouseEvent) => { + onIsOpenUpdate(false); + onClick(e); + }, + }) + ); + + return ( + setIsCategoryOpen(category.id, isCategoryOpen, storage)} + data-test-subj={`collapsibleNavGroup-${category.id}`} + > + + + ); + })} + + {/* Things with no category (largely for custom plugins) */} + {unknowns.map(({ label, href, icon, isActive, isDisabled, onClick }, i) => ( + + + ) => { + onIsOpenUpdate(false); + onClick(e); + }} + /> + + + ))} + + {/* Docking button only for larger screens that can support it*/} + + + + { + onIsLockedUpdate(!isLocked); + if (lockRef.current) { + lockRef.current.focus(); + } + }} + iconType={isLocked ? 'lock' : 'lockOpen'} + /> + + + +
+
+ ); +} diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx index 66b34c3db7bad..fb94ef46cdc2c 100644 --- a/src/core/public/chrome/ui/header/header.tsx +++ b/src/core/public/chrome/ui/header/header.tsx @@ -25,8 +25,8 @@ import { EuiIcon, // @ts-ignore EuiNavDrawer, - // @ts-ignore EuiShowFor, + htmlIdGenerator, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { Component, createRef } from 'react'; @@ -43,13 +43,14 @@ import { InternalApplicationStart } from '../../../application/types'; import { HttpStart } from '../../../http'; import { ChromeHelpExtension } from '../../chrome_service'; import { HeaderBadge } from './header_badge'; -import { OnIsLockedUpdate } from './'; +import { NavType, OnIsLockedUpdate } from './'; import { HeaderBreadcrumbs } from './header_breadcrumbs'; import { HeaderHelpMenu } from './header_help_menu'; import { HeaderNavControls } from './header_nav_controls'; -import { euiNavLink } from './nav_link'; +import { createNavLink, createRecentNavLink } from './nav_link'; import { HeaderLogo } from './header_logo'; import { NavDrawer } from './nav_drawer'; +import { CollapsibleNav } from './collapsible_nav'; export interface HeaderProps { kibanaVersion: string; @@ -70,6 +71,7 @@ export interface HeaderProps { navControlsRight$: Rx.Observable; basePath: HttpStart['basePath']; isLocked$: Rx.Observable; + navType$: Rx.Observable; onIsLockedUpdate: OnIsLockedUpdate; } @@ -83,11 +85,14 @@ interface State { navControlsRight: readonly ChromeNavControl[]; currentAppId: string | undefined; isLocked: boolean; + navType: NavType; + isOpen: boolean; } export class Header extends Component { private subscription?: Rx.Subscription; private navDrawerRef = createRef(); + private toggleCollapsibleNavRef = createRef(); constructor(props: HeaderProps) { super(props); @@ -105,6 +110,8 @@ export class Header extends Component { navControlsRight: [], currentAppId: '', isLocked, + navType: 'modern', + isOpen: false, }; } @@ -120,7 +127,8 @@ export class Header extends Component { this.props.navControlsLeft$, this.props.navControlsRight$, this.props.application.currentAppId$, - this.props.isLocked$ + this.props.isLocked$, + this.props.navType$ ) ).subscribe({ next: ([ @@ -129,7 +137,7 @@ export class Header extends Component { forceNavigation, navLinks, recentlyAccessed, - [navControlsLeft, navControlsRight, currentAppId, isLocked], + [navControlsLeft, navControlsRight, currentAppId, isLocked, navType], ]) => { this.setState({ appTitle, @@ -141,6 +149,7 @@ export class Header extends Component { navControlsRight, currentAppId, isLocked, + navType, }); }, }); @@ -176,7 +185,7 @@ export class Header extends Component { kibanaVersion, } = this.props; const navLinks = this.state.navLinks.map(link => - euiNavLink( + createNavLink( link, this.props.legacyMode, this.state.currentAppId, @@ -184,26 +193,54 @@ export class Header extends Component { this.props.application.navigateToApp ) ); + const recentNavLinks = this.state.recentlyAccessed.map(link => + createRecentNavLink(link, this.state.navLinks, this.props.basePath) + ); if (!isVisible) { return null; } const className = classnames( - 'chrHeaderWrapper', + 'chrHeaderWrapper', // TODO #64541 - delete this + 'hide-for-sharing', { 'chrHeaderWrapper--navIsLocked': this.state.isLocked, - }, - 'hide-for-sharing' + headerWrapper: this.state.navType === 'modern', + } ); - + const navId = htmlIdGenerator()(); return (
- + - - {this.renderMenuTrigger()} - + {this.state.navType === 'modern' ? ( + + { + this.setState({ isOpen: !this.state.isOpen }); + }} + aria-expanded={this.state.isOpen} + aria-pressed={this.state.isOpen} + aria-controls={navId} + ref={this.toggleCollapsibleNavRef} + > + + + + ) : ( + // TODO #64541 + // Delete this block + + + {this.renderMenuTrigger()} + + + )} { - + {this.state.navType === 'modern' ? ( + { + this.setState({ isOpen }); + if (this.toggleCollapsibleNavRef.current) { + this.toggleCollapsibleNavRef.current.focus(); + } + }} + /> + ) : ( + // TODO #64541 + // Delete this block + + )}
); } diff --git a/src/core/public/chrome/ui/header/index.ts b/src/core/public/chrome/ui/header/index.ts index 49e002a66d939..a492273a65ba8 100644 --- a/src/core/public/chrome/ui/header/index.ts +++ b/src/core/public/chrome/ui/header/index.ts @@ -18,6 +18,7 @@ */ export { Header, HeaderProps } from './header'; +export { OnIsLockedUpdate, NavType } from './types'; export { ChromeHelpExtensionMenuLink, ChromeHelpExtensionMenuCustomLink, @@ -25,4 +26,3 @@ export { ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, } from './header_help_menu'; -export type OnIsLockedUpdate = (isLocked: boolean) => void; diff --git a/src/core/public/chrome/ui/header/nav_drawer.tsx b/src/core/public/chrome/ui/header/nav_drawer.tsx index c57faec1e428d..7faee8edea43b 100644 --- a/src/core/public/chrome/ui/header/nav_drawer.tsx +++ b/src/core/public/chrome/ui/header/nav_drawer.tsx @@ -22,22 +22,18 @@ import { i18n } from '@kbn/i18n'; // @ts-ignore import { EuiNavDrawer, EuiHorizontalRule, EuiNavDrawerGroup } from '@elastic/eui'; import { OnIsLockedUpdate } from './'; -import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..'; -import { HttpStart } from '../../../http'; -import { NavLink } from './nav_link'; +import { NavLink, RecentNavLink } from './nav_link'; import { RecentLinks } from './recent_links'; export interface Props { isLocked?: boolean; onIsLockedUpdate?: OnIsLockedUpdate; navLinks: NavLink[]; - chromeNavLinks: ChromeNavLink[]; - recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[]; - basePath: HttpStart['basePath']; + recentNavLinks: RecentNavLink[]; } function navDrawerRenderer( - { isLocked, onIsLockedUpdate, navLinks, chromeNavLinks, recentlyAccessedItems, basePath }: Props, + { isLocked, onIsLockedUpdate, navLinks, recentNavLinks }: Props, ref: React.Ref ) { return ( @@ -50,11 +46,7 @@ function navDrawerRenderer( defaultMessage: 'Primary', })} > - {RecentLinks({ - recentlyAccessedItems, - navLinks: chromeNavLinks, - basePath, - })} + {RecentLinks({ recentNavLinks })} ) { return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey); } @@ -30,15 +32,36 @@ function LinkIcon({ url }: { url: string }) { return ; } -export type NavLink = ReturnType; +export interface NavLink { + key: string; + label: string; + href: string; + isActive: boolean; + onClick(event: React.MouseEvent): void; + category?: AppCategory; + isDisabled?: boolean; + iconType?: string; + icon?: JSX.Element; + order?: number; + 'data-test-subj': string; +} -export function euiNavLink( +/** + * Create a link that's actually ready to be passed into EUI + * + * @param navLink + * @param legacyMode + * @param currentAppId + * @param basePath + * @param navigateToApp + */ +export function createNavLink( navLink: ChromeNavLink, legacyMode: boolean, currentAppId: string | undefined, basePath: HttpStart['basePath'], navigateToApp: CoreStart['application']['navigateToApp'] -) { +): NavLink { const { legacy, url, @@ -64,7 +87,7 @@ export function euiNavLink( key: id, label: tooltip ?? title, href, // Use href and onClick to support "open in new tab" and SPA navigation in the same link - onClick(event: MouseEvent) { + onClick(event) { if ( !legacyMode && // ignore when in legacy mode !legacy && // ignore links to legacy apps @@ -85,3 +108,76 @@ export function euiNavLink( 'data-test-subj': 'navDrawerAppsMenuLink', }; } + +// Providing a buffer between the limit and the cut off index +// protects from truncating just the last couple (6) characters +const TRUNCATE_LIMIT: number = 64; +const TRUNCATE_AT: number = 58; + +function truncateRecentItemLabel(label: string): string { + if (label.length > TRUNCATE_LIMIT) { + label = `${label.substring(0, TRUNCATE_AT)}…`; + } + + return label; +} + +/** + * @param {string} url - a relative or root relative url. If a relative path is given then the + * absolute url returned will depend on the current page where this function is called from. For example + * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get + * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that + * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart". + * @return {string} the relative url transformed into an absolute url + */ +function relativeToAbsolute(url: string) { + const a = document.createElement('a'); + a.setAttribute('href', url); + return a.href; +} + +export interface RecentNavLink { + href: string; + label: string; + title: string; + 'aria-label': string; + iconType?: string; +} + +/** + * Add saved object type info to recently links + * + * Recent nav links are similar to normal nav links but are missing some Kibana Platform magic and + * because of legacy reasons have slightly different properties. + * @param recentLink + * @param navLinks + * @param basePath + */ +export function createRecentNavLink( + recentLink: ChromeRecentlyAccessedHistoryItem, + navLinks: ChromeNavLink[], + basePath: HttpStart['basePath'] +) { + const { link, label } = recentLink; + const href = relativeToAbsolute(basePath.prepend(link)); + const navLink = navLinks.find(nl => href.startsWith(nl.baseUrl ?? nl.subUrlBase)); + let titleAndAriaLabel = label; + + if (navLink) { + titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', { + defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', + values: { + recentlyAccessedItemLinklabel: label, + pageType: navLink.title, + }, + }); + } + + return { + href, + label: truncateRecentItemLabel(label), + title: titleAndAriaLabel, + 'aria-label': titleAndAriaLabel, + iconType: navLink?.euiIconType, + }; +} diff --git a/src/core/public/chrome/ui/header/recent_links.tsx b/src/core/public/chrome/ui/header/recent_links.tsx index 57cb1d9541bcd..019cdce0b43c6 100644 --- a/src/core/public/chrome/ui/header/recent_links.tsx +++ b/src/core/public/chrome/ui/header/recent_links.tsx @@ -21,73 +21,13 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; // @ts-ignore import { EuiNavDrawerGroup } from '@elastic/eui'; -import { ChromeNavLink, ChromeRecentlyAccessedHistoryItem } from '../../..'; -import { HttpStart } from '../../../http'; - -// Providing a buffer between the limit and the cut off index -// protects from truncating just the last couple (6) characters -const TRUNCATE_LIMIT: number = 64; -const TRUNCATE_AT: number = 58; - -export function truncateRecentItemLabel(label: string): string { - if (label.length > TRUNCATE_LIMIT) { - label = `${label.substring(0, TRUNCATE_AT)}…`; - } - - return label; -} - -/** - * @param {string} url - a relative or root relative url. If a relative path is given then the - * absolute url returned will depend on the current page where this function is called from. For example - * if you are on page "http://www.mysite.com/shopping/kids" and you pass this function "adults", you would get - * back "http://www.mysite.com/shopping/adults". If you passed this function a root relative path, or one that - * starts with a "/", for example "/account/cart", you would get back "http://www.mysite.com/account/cart". - * @return {string} the relative url transformed into an absolute url - */ -function relativeToAbsolute(url: string) { - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -} - -function prepareForEUI( - recentlyAccessed: ChromeRecentlyAccessedHistoryItem[], - navLinks: ChromeNavLink[], - basePath: HttpStart['basePath'] -) { - return recentlyAccessed.map(({ link, label }) => { - const href = relativeToAbsolute(basePath.prepend(link)); - const navLink = navLinks.find(nl => href.startsWith(nl.baseUrl ?? nl.subUrlBase)); - let titleAndAriaLabel = label; - - if (navLink) { - titleAndAriaLabel = i18n.translate('core.ui.recentLinks.linkItem.screenReaderLabel', { - defaultMessage: '{recentlyAccessedItemLinklabel}, type: {pageType}', - values: { - recentlyAccessedItemLinklabel: label, - pageType: navLink.title, - }, - }); - } - - return { - href, - label: truncateRecentItemLabel(label), - title: titleAndAriaLabel, - 'aria-label': titleAndAriaLabel, - iconType: navLink?.euiIconType, - }; - }); -} +import { RecentNavLink } from './nav_link'; interface Props { - recentlyAccessedItems: ChromeRecentlyAccessedHistoryItem[]; - navLinks: ChromeNavLink[]; - basePath: HttpStart['basePath']; + recentNavLinks: RecentNavLink[]; } -export function RecentLinks({ recentlyAccessedItems, navLinks, basePath }: Props) { +export function RecentLinks({ recentNavLinks }: Props) { return ( void; +export type NavType = 'modern' | 'legacy'; diff --git a/src/core/public/chrome/ui/index.ts b/src/core/public/chrome/ui/index.ts index 460e19b7d9780..4f6ad90cb96a3 100644 --- a/src/core/public/chrome/ui/index.ts +++ b/src/core/public/chrome/ui/index.ts @@ -25,4 +25,5 @@ export { ChromeHelpExtensionMenuDiscussLink, ChromeHelpExtensionMenuDocumentationLink, ChromeHelpExtensionMenuGitHubLink, + NavType, } from './header'; diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 59f0142bb8890..e58114b69dcc1 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -240,6 +240,7 @@ export class CoreSystem { http, injectedMetadata, notifications, + uiSettings, }); application.registerMountContext(this.coreContext.coreId, 'core', () => ({ diff --git a/src/core/public/index.ts b/src/core/public/index.ts index c30996b83c946..3b2d9ed3c0b02 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -54,6 +54,7 @@ import { ChromeStart, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, + NavType, } from './chrome'; import { FatalErrorsSetup, FatalErrorsStart, FatalErrorInfo } from './fatal_errors'; import { HttpSetup, HttpStart } from './http'; @@ -354,4 +355,5 @@ export { PluginOpaqueId, IUiSettingsClient, UiSettingsState, + NavType, }; diff --git a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap index 6b4b22b8541bc..fa83b34e06b81 100644 --- a/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap +++ b/src/core/public/overlays/flyout/__snapshots__/flyout_service.test.tsx.snap @@ -13,12 +13,7 @@ Array [ Array [
Flyout content
"`; +exports[`FlyoutService openFlyout() renders a flyout to the DOM 2`] = `"
Flyout content
"`; exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 1`] = ` Array [ Array [
Flyout content 2
"`; +exports[`FlyoutService openFlyout() with a currently active flyout replaces the current flyout with a new one 2`] = `"
Flyout content 2
"`; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index c9fad5952bc7a..225ef611c0298 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -55,6 +55,7 @@ export interface AppBase { export interface AppCategory { ariaLabel?: string; euiIconType?: string; + id: string; label: string; order?: number; } @@ -343,6 +344,7 @@ export interface ChromeStart { getHelpExtension$(): Observable; getIsNavDrawerLocked$(): Observable; getIsVisible$(): Observable; + getNavType$(): Observable; navControls: ChromeNavControls; navLinks: ChromeNavLinks; recentlyAccessed: ChromeRecentlyAccessed; @@ -443,23 +445,28 @@ export function deepFreeze(object: T): RecursiveReadonly // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ - analyze: { + kibana: { + id: string; label: string; + euiIconType: string; order: number; }; observability: { + id: string; label: string; euiIconType: string; order: number; }; security: { + id: string; label: string; order: number; euiIconType: string; }; management: { + id: string; label: string; - euiIconType: string; + order: number; }; }>; @@ -883,6 +890,11 @@ export function modifyUrl(url: string, urlModifier: (urlParts: URLMeaningfulPart // @public export type MountPoint = (element: T) => UnmountCallback; +// Warning: (ae-missing-release-tag) "NavType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type NavType = 'modern' | 'legacy'; + // @public (undocumented) export interface NotificationsSetup { // (undocumented) diff --git a/src/core/public/rendering/_base.scss b/src/core/public/rendering/_base.scss index ff28fc75e367d..8032bc458822f 100644 --- a/src/core/public/rendering/_base.scss +++ b/src/core/public/rendering/_base.scss @@ -1,3 +1,6 @@ +@import '@elastic/eui/src/components/header/variables'; +@import '@elastic/eui/src/components/nav_drawer/variables'; + /** * stretch the root element of the Kibana application to set the base-size that * flexed children should keep. Only works when paired with root styles applied @@ -9,7 +12,9 @@ min-height: 100%; } -.app-wrapper { +// TODO #64541 +// Delete this block +.chrHeaderWrapper:not(.headerWrapper) ~ .app-wrapper { display: flex; flex-flow: column nowrap; position: absolute; @@ -20,6 +25,22 @@ z-index: 5; margin: 0 auto; + &:not(.hidden-chrome) { + top: $euiHeaderChildSize; + left: $euiHeaderChildSize; + + // HOTFIX: Temporary fix for flyouts not inside portals + // SASSTODO: Find an actual solution + .euiFlyout { + top: $euiHeaderChildSize; + height: calc(100% - #{$euiHeaderChildSize}); + } + + @include euiBreakpoint('xs', 's') { + left: 0; + } + } + /** * 1. Dirty, but we need to override the .kbnGlobalNav-isOpen state * when we're looking at the log-in screen. @@ -33,6 +54,32 @@ } } +// TODO #64541 +// Delete this block +@include euiBreakpoint('xl') { + .chrHeaderWrapper--navIsLocked:not(.headerWrapper) { + ~ .app-wrapper:not(.hidden-chrome) { + // Shrink the content from the left so it's no longer overlapped by the nav drawer (ALWAYS) + left: $euiNavDrawerWidthExpanded !important; // sass-lint:disable-line no-important + transition: left $euiAnimSpeedFast $euiAnimSlightResistance; + } + } +} + +// TODO #64541 +// Remove .headerWrapper and header conditionals +.headerWrapper ~ .app-wrapper, +:not(header) ~ .app-wrapper { + display: flex; + flex-flow: column nowrap; + margin: 0 auto; + min-height: calc(100vh - #{$euiHeaderHeightCompensation}); + + &.hidden-chrome { + min-height: 100vh; + } +} + .app-wrapper-panel { display: flex; flex-grow: 1; diff --git a/src/core/server/legacy/plugins/get_nav_links.test.ts b/src/core/server/legacy/plugins/get_nav_links.test.ts index 44d080ec37a25..5e84f27acabd5 100644 --- a/src/core/server/legacy/plugins/get_nav_links.test.ts +++ b/src/core/server/legacy/plugins/get_nav_links.test.ts @@ -133,6 +133,7 @@ describe('getNavLinks', () => { id: 'app-a', title: 'AppA', category: { + id: 'foo', label: 'My Category', }, order: 42, @@ -151,6 +152,7 @@ describe('getNavLinks', () => { id: 'app-a', title: 'AppA', category: { + id: 'foo', label: 'My Category', }, order: 42, @@ -211,6 +213,7 @@ describe('getNavLinks', () => { id: 'link-a', title: 'AppA', category: { + id: 'foo', label: 'My Second Cat', }, order: 72, @@ -232,6 +235,7 @@ describe('getNavLinks', () => { id: 'link-a', title: 'AppA', category: { + id: 'foo', label: 'My Second Cat', }, order: 72, diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 54b7a2ada69ad..62d11ee7cf9a7 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -700,23 +700,28 @@ export function deepFreeze(object: T): RecursiveReadonly // @internal (undocumented) export const DEFAULT_APP_CATEGORIES: Readonly<{ - analyze: { + kibana: { + id: string; label: string; + euiIconType: string; order: number; }; observability: { + id: string; label: string; euiIconType: string; order: number; }; security: { + id: string; label: string; order: number; euiIconType: string; }; management: { + id: string; label: string; - euiIconType: string; + order: number; }; }>; diff --git a/src/core/types/app_category.ts b/src/core/types/app_category.ts index 83a3693f009b6..8b39889b43a82 100644 --- a/src/core/types/app_category.ts +++ b/src/core/types/app_category.ts @@ -24,6 +24,11 @@ * @public */ export interface AppCategory { + /** + * Unique identifier for the categories + */ + id: string; + /** * Label used for cateogry name. * Also used as aria-label if one isn't set. diff --git a/src/core/utils/default_app_categories.ts b/src/core/utils/default_app_categories.ts index 2285bd6afd365..5708bcfeac31a 100644 --- a/src/core/utils/default_app_categories.ts +++ b/src/core/utils/default_app_categories.ts @@ -21,13 +21,16 @@ import { i18n } from '@kbn/i18n'; /** @internal */ export const DEFAULT_APP_CATEGORIES = Object.freeze({ - analyze: { - label: i18n.translate('core.ui.analyzeNavList.label', { - defaultMessage: 'Analyze', + kibana: { + id: 'kibana', + label: i18n.translate('core.ui.kibanaNavList.label', { + defaultMessage: 'Kibana', }), + euiIconType: 'logoKibana', order: 1000, }, observability: { + id: 'observability', label: i18n.translate('core.ui.observabilityNavList.label', { defaultMessage: 'Observability', }), @@ -35,6 +38,7 @@ export const DEFAULT_APP_CATEGORIES = Object.freeze({ order: 2000, }, security: { + id: 'security', label: i18n.translate('core.ui.securityNavList.label', { defaultMessage: 'Security', }), @@ -42,9 +46,10 @@ export const DEFAULT_APP_CATEGORIES = Object.freeze({ euiIconType: 'logoSecurity', }, management: { + id: 'management', label: i18n.translate('core.ui.managementNavList.label', { defaultMessage: 'Management', }), - euiIconType: 'managementApp', + order: 5000, }, }); diff --git a/src/legacy/core_plugins/kibana/index.js b/src/legacy/core_plugins/kibana/index.js index e786890567740..6664cf0d7366d 100644 --- a/src/legacy/core_plugins/kibana/index.js +++ b/src/legacy/core_plugins/kibana/index.js @@ -67,33 +67,33 @@ export default function(kibana) { title: i18n.translate('kbn.discoverTitle', { defaultMessage: 'Discover', }), - order: -1003, + order: 2000, url: `${kbnBaseUrl}#/discover`, euiIconType: 'discoverApp', disableSubUrlTracking: true, - category: DEFAULT_APP_CATEGORIES.analyze, + category: DEFAULT_APP_CATEGORIES.kibana, }, { id: 'kibana:visualize', title: i18n.translate('kbn.visualizeTitle', { defaultMessage: 'Visualize', }), - order: -1002, + order: 7000, url: `${kbnBaseUrl}#/visualize`, euiIconType: 'visualizeApp', disableSubUrlTracking: true, - category: DEFAULT_APP_CATEGORIES.analyze, + category: DEFAULT_APP_CATEGORIES.kibana, }, { id: 'kibana:dashboard', title: i18n.translate('kbn.dashboardTitle', { defaultMessage: 'Dashboard', }), - order: -1001, + order: 1000, url: `${kbnBaseUrl}#/dashboards`, euiIconType: 'dashboardApp', disableSubUrlTracking: true, - category: DEFAULT_APP_CATEGORIES.analyze, + category: DEFAULT_APP_CATEGORIES.kibana, }, { id: 'kibana:dev_tools', @@ -108,7 +108,7 @@ export default function(kibana) { { id: 'kibana:stack_management', title: i18n.translate('kbn.managementTitle', { - defaultMessage: 'Management', + defaultMessage: 'Stack Management', }), order: 9003, url: `${kbnBaseUrl}#/management`, diff --git a/src/legacy/core_plugins/kibana/public/management/index.js b/src/legacy/core_plugins/kibana/public/management/index.js index 6a36391c56b5c..2cba9fab7be22 100644 --- a/src/legacy/core_plugins/kibana/public/management/index.js +++ b/src/legacy/core_plugins/kibana/public/management/index.js @@ -69,7 +69,7 @@ export function updateLandingPage(version) {

diff --git a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js index 64b7dfe22fd57..91c61886d216c 100644 --- a/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/server/ui_setting_defaults.js @@ -1172,5 +1172,25 @@ export function getUiSettingDefaults() { category: ['accessibility'], requiresPageReload: true, }, + pageNavigation: { + name: i18n.translate('kbn.advancedSettings.pageNavigationName', { + defaultMessage: 'Side nav style', + }), + value: 'modern', + description: i18n.translate('kbn.advancedSettings.pageNavigationDesc', { + defaultMessage: 'Change the style of navigation', + }), + type: 'select', + options: ['modern', 'legacy'], + optionLabels: { + modern: i18n.translate('kbn.advancedSettings.pageNavigationModern', { + defaultMessage: 'Modern', + }), + legacy: i18n.translate('kbn.advancedSettings.pageNavigationLegacy', { + defaultMessage: 'Legacy', + }), + }, + schema: schema.oneOf([schema.literal('modern'), schema.literal('legacy')]), + }, }; } diff --git a/src/legacy/core_plugins/timelion/index.ts b/src/legacy/core_plugins/timelion/index.ts index 4fdf27d7cf655..31926f658ec13 100644 --- a/src/legacy/core_plugins/timelion/index.ts +++ b/src/legacy/core_plugins/timelion/index.ts @@ -54,11 +54,11 @@ const timelionPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPl uiExports: { app: { title: 'Timelion', - order: -1000, + order: 8000, icon: 'plugins/timelion/icon.svg', euiIconType: 'timelionApp', main: 'plugins/timelion/app', - category: DEFAULT_APP_CATEGORIES.analyze, + category: DEFAULT_APP_CATEGORIES.kibana, }, styleSheetPaths: resolve(__dirname, 'public/index.scss'), hacks: [resolve(__dirname, 'public/legacy')], diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap index cba8e85a65249..f0766df176c0d 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap +++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap @@ -4,12 +4,7 @@ exports[`LabelTemplateFlyout should not render if not visible 1`] = `""`; exports[`LabelTemplateFlyout should render normally 1`] = ` diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap index 849e307f7b527..fd697a2a4c70a 100644 --- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap +++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.tsx.snap @@ -4,12 +4,7 @@ exports[`UrlTemplateFlyout should not render if not visible 1`] = `""`; exports[`UrlTemplateFlyout should render normally 1`] = ` diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap index 282e8e311d984..6991281dc86a9 100644 --- a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap +++ b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap @@ -2,13 +2,8 @@ exports[`ScriptingHelpFlyout should render normally 1`] = ` { renderBottomBar = () => { const areChangesInvalid = this.areChangesInvalid(); - const bottomBarClasses = classNames('mgtAdvancedSettingsForm__bottomBar', { - 'mgtAdvancedSettingsForm__bottomBar--pushForNav': - localStorage.getItem(NAV_IS_LOCKED_KEY) === 'true', - }); + + // TODO #64541 + // Delete these classes + let bottomBarClasses = ''; + const pageNav = this.props.settings.general.find(setting => setting.name === 'pageNavigation'); + + if (pageNav?.value === 'legacy') { + bottomBarClasses = classNames('mgtAdvancedSettingsForm__bottomBar', { + 'mgtAdvancedSettingsForm__bottomBar--pushForNav': + localStorage.getItem(NAV_IS_LOCKED_KEY) === 'true', + }); + } return ( extends Component< +export class PhraseSuggestorUI extends React.Component< T, PhraseSuggestorState > { diff --git a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx index 6ca1b7582001f..8ad1b5d392f3b 100644 --- a/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx +++ b/src/plugins/data/public/ui/saved_query_management/saved_query_management_component.tsx @@ -180,6 +180,7 @@ export function SavedQueryManagementComponent({ }} anchorPosition="downLeft" panelPaddingSize="none" + buffer={-8} ownFocus >
= ({ ); const ariaLabelWithoutTitle = i18n.translate( 'embeddableApi.panel.optionsMenu.panelOptionsButtonAriaLabel', - { - defaultMessage: 'Panel options', - } + { defaultMessage: 'Panel options' } ); const button = ( diff --git a/src/plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap b/src/plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap index 43e2af6d099e8..eab52795fefaa 100644 --- a/src/plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap +++ b/src/plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap @@ -8,6 +8,7 @@ exports[`disableMsg 1`] = ` label="list control" > diff --git a/src/plugins/input_control_vis/public/components/vis/list_control.tsx b/src/plugins/input_control_vis/public/components/vis/list_control.tsx index 6ded66917a3fd..cf95eed470beb 100644 --- a/src/plugins/input_control_vis/public/components/vis/list_control.tsx +++ b/src/plugins/input_control_vis/public/components/vis/list_control.tsx @@ -114,6 +114,10 @@ class ListControlUi extends PureComponent void; - min?: ValueMember; - max?: ValueMember; + min?: number; + max?: number; } interface State { @@ -72,6 +72,18 @@ export class ValidatedDualRange extends Component { return null; } + // Can remove after eui#3412 is resolved + componentDidMount() { + if (this.trackRef.current) { + const track = this.trackRef.current.querySelector('.euiRangeTrack'); + if (track) { + track.setAttribute('aria-hidden', 'true'); + } + } + } + + trackRef = createRef(); + // @ts-ignore state populated by getDerivedStateFromProps state: State = {}; @@ -103,29 +115,38 @@ export class ValidatedDualRange extends Component { value, // eslint-disable-line no-unused-vars onChange, // eslint-disable-line no-unused-vars allowEmptyRange, // eslint-disable-line no-unused-vars - // @ts-ignore ...rest // TODO: Consider alternatives for spread operator in component } = this.props; return ( - - + - + isInvalid={!this.state.isValid} + error={this.state.errorMessage ? [this.state.errorMessage] : []} + label={label} + display={formRowDisplay} + > + + +
); } } diff --git a/src/plugins/management/public/legacy/sections_register.js b/src/plugins/management/public/legacy/sections_register.js index 63d919377f89e..aae58ba3e4651 100644 --- a/src/plugins/management/public/legacy/sections_register.js +++ b/src/plugins/management/public/legacy/sections_register.js @@ -27,7 +27,7 @@ export class LegacyManagementAdapter { 'management', { display: i18n.translate('management.displayName', { - defaultMessage: 'Management', + defaultMessage: 'Stack Management', }), }, capabilities diff --git a/src/plugins/management/public/management_app.tsx b/src/plugins/management/public/management_app.tsx index 38db1039042e5..843bbfde654ee 100644 --- a/src/plugins/management/public/management_app.tsx +++ b/src/plugins/management/public/management_app.tsx @@ -64,7 +64,7 @@ export class ManagementApp { coreStart.chrome.setBreadcrumbs([ { text: i18n.translate('management.breadcrumb', { - defaultMessage: 'Management', + defaultMessage: 'Stack Management', }), href: '#/management', }, diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.ts index 1c9e1d5c89550..df2398412dac2 100644 --- a/src/plugins/management/public/plugin.ts +++ b/src/plugins/management/public/plugin.ts @@ -36,8 +36,8 @@ export class ManagementPlugin implements Plugin diff --git a/src/plugins/ui_actions/public/actions/action_internal.ts b/src/plugins/ui_actions/public/actions/action_internal.ts index 4cbc4dd2a053c..e3504c7c5d301 100644 --- a/src/plugins/ui_actions/public/actions/action_internal.ts +++ b/src/plugins/ui_actions/public/actions/action_internal.ts @@ -17,6 +17,8 @@ * under the License. */ +// @ts-ignore +import React from 'react'; import { Action, ActionContext as Context, ActionDefinition } from './action'; import { Presentable } from '../util/presentable'; import { uiToReactComponent } from '../../../kibana_react/public'; diff --git a/src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap b/src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap index afaea0d9b8462..43fc2671ba42a 100644 --- a/src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap +++ b/src/plugins/visualizations/public/components/__snapshots__/visualization_noresults.test.js.snap @@ -17,7 +17,6 @@ exports[`VisualizationNoResults should render according to snapshot 1`] = ` class="euiTextColor euiTextColor--subdued" >