diff --git a/.eslintrc.js b/.eslintrc.js index 5341c63e52e36..5a5648935685a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1113,7 +1113,7 @@ module.exports = { { files: [ 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', - 'x-pack/plugins/cases/public/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/cases/**/*.{js,mjs,ts,tsx}', ], rules: { '@typescript-eslint/consistent-type-imports': 'error', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e19165cf4faa1..91e4463aa9905 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -18,6 +18,7 @@ /x-pack/plugins/graph/ @elastic/kibana-data-discovery /x-pack/test/functional/apps/graph @elastic/kibana-data-discovery /src/plugins/unified_field_list/ @elastic/kibana-data-discovery +/src/plugins/unified_histogram/ @elastic/kibana-data-discovery /src/plugins/saved_objects_finder/ @elastic/kibana-data-discovery # Vis Editors diff --git a/.i18nrc.json b/.i18nrc.json index 5f0d6b1d2e30a..246f0ff484863 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -97,7 +97,8 @@ "visTypeXy": "src/plugins/vis_types/xy", "visualizations": "src/plugins/visualizations", "unifiedSearch": "src/plugins/unified_search", - "unifiedFieldList": "src/plugins/unified_field_list" + "unifiedFieldList": "src/plugins/unified_field_list", + "unifiedHistogram": "src/plugins/unified_histogram" }, "translations": [] } diff --git a/api_docs/actions.devdocs.json b/api_docs/actions.devdocs.json index c20f6e15fb966..0f63f83fedf12 100644 --- a/api_docs/actions.devdocs.json +++ b/api_docs/actions.devdocs.json @@ -1389,6 +1389,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "actions", + "id": "def-server.ActionTypeExecutorOptions.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + "Logger" + ], + "path": "x-pack/plugins/actions/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "actions", "id": "def-server.ActionTypeExecutorOptions.isEphemeral", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 44a8da932ebdf..c3eb06615e8f8 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 213 | 0 | 208 | 23 | +| 214 | 0 | 209 | 23 | ## Client diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index c9f06a7fd2960..3f764836650f8 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index e8173cc57239e..cfabe6b38aaa1 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index 4c8345c2bc602..2e701198049b0 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -1902,6 +1902,20 @@ "path": "x-pack/plugins/alerting/server/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-server.RuleExecutorOptions.logger", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + "Logger" + ], + "path": "x-pack/plugins/alerting/server/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index e66c835cde417..556859658e63b 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 381 | 0 | 372 | 24 | +| 382 | 0 | 373 | 24 | ## Client diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 017ae6a510700..7fd8519951fc6 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -3703,7 +3703,7 @@ "section": "def-server.APMRouteHandlerResources", "text": "APMRouteHandlerResources" }, - ", { samples: { traceId: string; transactionId: string; }[]; }, ", + ", { traceSamples: { traceId: string; transactionId: string; }[]; }, ", "APMRouteCreateOptions", ">; \"GET /internal/apm/transactions/{transactionId}\": ", "ServerRoute", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index c55852de2cb5a..5ceacebf9e42c 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 0104cb6bda448..2a1de0f673861 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 1062c61b4eb77..d99310156b987 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index dd47790528e13..0fc9007e20b60 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index a170a098ef509..2fc8e1a6c41d0 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index ec60bb2bf7937..a87e142890f08 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.devdocs.json b/api_docs/cloud.devdocs.json index 89134783e726f..e86310156f1c1 100644 --- a/api_docs/cloud.devdocs.json +++ b/api_docs/cloud.devdocs.json @@ -101,13 +101,27 @@ }, { "parentPluginId": "cloud", - "id": "def-public.CloudConfigType.full_story", - "type": "Object", + "id": "def-public.CloudConfigType.trial_end_date", + "type": "string", + "tags": [], + "label": "trial_end_date", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudConfigType.is_elastic_staff_owned", + "type": "CompoundType", "tags": [], - "label": "full_story", + "label": "is_elastic_staff_owned", "description": [], "signature": [ - "{ enabled: boolean; org_id?: string | undefined; eventTypesAllowlist?: string[] | undefined; }" + "boolean | undefined" ], "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false, @@ -275,7 +289,9 @@ "type": "string", "tags": [], "label": "cloudId", - "description": [], + "description": [ + "\nCloud ID. Undefined if not running on Cloud." + ], "signature": [ "string | undefined" ], @@ -289,7 +305,9 @@ "type": "string", "tags": [], "label": "cname", - "description": [], + "description": [ + "\nThis value is the same as `baseUrl` on ESS but can be customized on ECE." + ], "signature": [ "string | undefined" ], @@ -303,7 +321,9 @@ "type": "string", "tags": [], "label": "baseUrl", - "description": [], + "description": [ + "\nThis is the URL of the Cloud interface." + ], "signature": [ "string | undefined" ], @@ -317,7 +337,9 @@ "type": "string", "tags": [], "label": "deploymentUrl", - "description": [], + "description": [ + "\nThe full URL to the deployment management page on Elastic Cloud. Undefined if not running on Cloud." + ], "signature": [ "string | undefined" ], @@ -331,7 +353,9 @@ "type": "string", "tags": [], "label": "profileUrl", - "description": [], + "description": [ + "\nThe full URL to the user profile page on Elastic Cloud. Undefined if not running on Cloud." + ], "signature": [ "string | undefined" ], @@ -345,7 +369,9 @@ "type": "string", "tags": [], "label": "organizationUrl", - "description": [], + "description": [ + "\nThe full URL to the organization management page on Elastic Cloud. Undefined if not running on Cloud." + ], "signature": [ "string | undefined" ], @@ -359,7 +385,9 @@ "type": "string", "tags": [], "label": "snapshotsUrl", - "description": [], + "description": [ + "\nThis is the path to the Snapshots page for the deployment to which the Kibana instance belongs. The value is already prepended with `deploymentUrl`." + ], "signature": [ "string | undefined" ], @@ -373,7 +401,41 @@ "type": "boolean", "tags": [], "label": "isCloudEnabled", - "description": [], + "description": [ + "\n`true` when Kibana is running on Elastic Cloud." + ], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudSetup.trialEndDate", + "type": "Object", + "tags": [], + "label": "trialEndDate", + "description": [ + "\nWhen the Cloud Trial ends/ended for the organization that owns this deployment. Only available when running on Elastic Cloud." + ], + "signature": [ + "Date | undefined" + ], + "path": "x-pack/plugins/cloud/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloud", + "id": "def-public.CloudSetup.isElasticStaffOwned", + "type": "CompoundType", + "tags": [], + "label": "isElasticStaffOwned", + "description": [ + "\n`true` if the Elastic Cloud organization that owns this deployment is owned by an Elastician. Only available when running on Elastic Cloud." + ], + "signature": [ + "boolean | undefined" + ], "path": "x-pack/plugins/cloud/public/plugin.tsx", "deprecated": false, "trackAdoption": false @@ -384,7 +446,9 @@ "type": "Function", "tags": [], "label": "registerCloudService", - "description": [], + "description": [ + "\nRegisters CloudServiceProviders so start's `CloudContextProvider` hooks them." + ], "signature": [ "(contextProvider: React.FC<{}>) => void" ], @@ -398,7 +462,9 @@ "type": "Function", "tags": [], "label": "contextProvider", - "description": [], + "description": [ + "The React component from the Service Provider." + ], "signature": [ "React.FC<{}>" ], @@ -428,7 +494,9 @@ "type": "Interface", "tags": [], "label": "CloudSetup", - "description": [], + "description": [ + "\nSetup contract" + ], "path": "x-pack/plugins/cloud/server/plugin.ts", "deprecated": false, "trackAdoption": false, @@ -439,7 +507,9 @@ "type": "string", "tags": [], "label": "cloudId", - "description": [], + "description": [ + "\nThe deployment's Cloud ID. Only available when running on Elastic Cloud." + ], "signature": [ "string | undefined" ], @@ -453,7 +523,9 @@ "type": "string", "tags": [], "label": "deploymentId", - "description": [], + "description": [ + "\nThe deployment's ID. Only available when running on Elastic Cloud." + ], "signature": [ "string | undefined" ], @@ -467,7 +539,9 @@ "type": "boolean", "tags": [], "label": "isCloudEnabled", - "description": [], + "description": [ + "\n`true` when running on Elastic Cloud." + ], "path": "x-pack/plugins/cloud/server/plugin.ts", "deprecated": false, "trackAdoption": false @@ -478,7 +552,9 @@ "type": "number", "tags": [], "label": "instanceSizeMb", - "description": [], + "description": [ + "\nThe size of the instance in which Kibana is running. Only available when running on Elastic Cloud." + ], "signature": [ "number | undefined" ], @@ -486,13 +562,47 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "cloud", + "id": "def-server.CloudSetup.trialEndDate", + "type": "Object", + "tags": [], + "label": "trialEndDate", + "description": [ + "\nWhen the Cloud Trial ends/ended for the organization that owns this deployment. Only available when running on Elastic Cloud." + ], + "signature": [ + "Date | undefined" + ], + "path": "x-pack/plugins/cloud/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "cloud", + "id": "def-server.CloudSetup.isElasticStaffOwned", + "type": "CompoundType", + "tags": [], + "label": "isElasticStaffOwned", + "description": [ + "\n`true` if the Elastic Cloud organization that owns this deployment is owned by an Elastician. Only available when running on Elastic Cloud." + ], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/cloud/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "cloud", "id": "def-server.CloudSetup.apm", "type": "Object", "tags": [], "label": "apm", - "description": [], + "description": [ + "\nAPM configuration keys." + ], "signature": [ "{ url?: string | undefined; secretToken?: string | undefined; }" ], diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index ac208319e2e02..d857e34b3b9e2 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 34 | 0 | 26 | 0 | +| 39 | 0 | 11 | 0 | ## Client diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 9dada4c4dd04e..dbcb36118fde6 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 3d656220231ff..4be455a506123 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 7c4195e373d96..0a9b7d2375dab 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index eef60631d7706..b51c199d10cd5 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index f475769e816dc..601df2f5255ab 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.mdx b/api_docs/core.mdx index a2435d5368b9b..2ec3f0a7262ec 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 141e578ac4fc7..b0c5dab3f98fa 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.devdocs.json b/api_docs/dashboard.devdocs.json index c185507fd9101..a4309f565cf9f 100644 --- a/api_docs/dashboard.devdocs.json +++ b/api_docs/dashboard.devdocs.json @@ -288,6 +288,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "dashboard", + "id": "def-public.DashboardContainerInput.syncCursor", + "type": "CompoundType", + "tags": [], + "label": "syncCursor", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/dashboard/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "dashboard", "id": "def-public.DashboardContainerInput.viewMode", diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 4298c36f86195..8b7de334deda8 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-prese | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 120 | 0 | 113 | 3 | +| 121 | 0 | 114 | 3 | ## Client diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index b92690c335ea4..369c9dc006fdb 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 6bc8d66273ed2..d49e7e4e2c3d8 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 13aa66ad4c1bb..23441aa926576 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index afe45496b9cc4..925a4fbb81958 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 9b182a62c9bba..7917daf25e25b 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 7618ea5a3857d..d34da2a7332b8 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 88419f85fef70..e94f7afe6585c 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index ea1a50769ae6f..df78232d00397 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 589d097fd6ec3..9a764354b95ee 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 294b8baa0a135..5b3d01cb4eae2 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 77d7f9b7f82e7..f12a4c2d6b469 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -751,8 +751,8 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 18 more | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 4 more | - | -| | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | -| | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | +| | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 5 more | 8.8.0 | +| | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 5 more | 8.8.0 | | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | | | [request_context_factory.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [request_context_factory.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [create_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts#:~:text=authc), [delete_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts#:~:text=authc), [finalize_signals_migration_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts#:~:text=authc), [open_close_signals_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/open_close_signals_route.ts#:~:text=authc), [preview_rules_route.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts#:~:text=authc), [common.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/timeline/utils/common.ts#:~:text=authc) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/index.tsx#:~:text=onAppLeave), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/plugin.tsx#:~:text=onAppLeave) | 8.8.0 | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 051dd9119b418..4aeef7cf6dc85 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -163,8 +163,8 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | -| securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [list.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts#:~:text=mode), [response_actions.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts#:~:text=mode)+ 3 more | 8.8.0 | +| securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 5 more | 8.8.0 | +| securitySolution | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 5 more | 8.8.0 | | securitySolution | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | | securitySolution | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/index.tsx#:~:text=onAppLeave), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/plugin.tsx#:~:text=onAppLeave) | 8.8.0 | | securitySolution | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/types.ts#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/app/app.tsx#:~:text=AppLeaveHandler), [use_timeline_save_prompt.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts#:~:text=AppLeaveHandler)+ 1 more | 8.8.0 | diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index d475502a928d2..ef1cdd9b4d903 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 0987eb3d36c0d..0010b677e5e12 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index b9258ccd6cff9..f117d9d140edb 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index 20bcffaab5464..21a6b55795244 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -9750,7 +9750,7 @@ }, " | undefined; title?: string | undefined; id: string; lastReloadRequestTime?: number | undefined; hidePanelTitles?: boolean | undefined; enhancements?: ", "SerializableRecord", - " | undefined; disabledActions?: string[] | undefined; disableTriggers?: boolean | undefined; searchSessionId?: string | undefined; syncColors?: boolean | undefined; syncTooltips?: boolean | undefined; executionContext?: ", + " | undefined; disabledActions?: string[] | undefined; disableTriggers?: boolean | undefined; searchSessionId?: string | undefined; syncColors?: boolean | undefined; syncCursor?: boolean | undefined; syncTooltips?: boolean | undefined; executionContext?: ", "KibanaExecutionContext", " | undefined; }" ], @@ -11328,7 +11328,7 @@ }, " | undefined; title?: string | undefined; id: string; lastReloadRequestTime?: number | undefined; hidePanelTitles?: boolean | undefined; enhancements?: ", "SerializableRecord", - " | undefined; disabledActions?: string[] | undefined; disableTriggers?: boolean | undefined; searchSessionId?: string | undefined; syncColors?: boolean | undefined; syncTooltips?: boolean | undefined; executionContext?: ", + " | undefined; disabledActions?: string[] | undefined; disableTriggers?: boolean | undefined; searchSessionId?: string | undefined; syncColors?: boolean | undefined; syncCursor?: boolean | undefined; syncTooltips?: boolean | undefined; executionContext?: ", "KibanaExecutionContext", " | undefined; }" ], diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index d87fd71d4813b..1c24dc1085f49 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index d0efc7d058262..f194611543bbe 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index fb272c39b3337..dc36561519d20 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 6911b0f2b73c9..9a499860128c3 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 7c24943a52254..25830dc3d3aad 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 46c72c5979803..bcdc6a18969af 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 56f2a42cafcd9..4a8ab4c9d8582 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index bd779d168e848..e94fab0683d54 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index fb3222340a00b..66ff63b20ef9c 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.devdocs.json b/api_docs/expression_heatmap.devdocs.json index 4e53b8fde2123..101973f84ca4d 100644 --- a/api_docs/expression_heatmap.devdocs.json +++ b/api_docs/expression_heatmap.devdocs.json @@ -447,6 +447,17 @@ "path": "src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressionHeatmap", + "id": "def-common.HeatmapExpressionProps.syncCursor", + "type": "boolean", + "tags": [], + "label": "syncCursor", + "description": [], + "path": "src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -620,7 +631,7 @@ "section": "def-public.PersistedState", "text": "PersistedState" }, - "; interactive: boolean; syncTooltips: boolean; renderComplete: () => void; }" + "; interactive: boolean; syncTooltips: boolean; syncCursor: boolean; renderComplete: () => void; }" ], "path": "src/plugins/chart_expressions/expression_heatmap/common/types/expression_renderers.ts", "deprecated": false, diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 17065861981cd..4204207ac8d9b 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 106 | 0 | 102 | 3 | +| 107 | 0 | 103 | 3 | ## Common diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 9933dd2032597..979751224d794 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 9de9393a41450..061799006b8bd 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 75bd75b868b0e..7b900f28b3f2f 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 961ffc0eecfd3..24d8613e4804b 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 4aca4e034dfdb..ad2cff13b95ca 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index c447ec5bc621e..e9bff50c4d86a 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 85ef888dd171d..2c1e776d19ead 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 3a310b469bf9a..910cb27bdb971 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 4d815ed16bb29..b5e97db3ffe59 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.devdocs.json b/api_docs/expression_x_y.devdocs.json index 9378c2a614083..1ed51d6360c13 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -1803,6 +1803,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "expressionXY", + "id": "def-common.XYChartProps.syncCursor", + "type": "boolean", + "tags": [], + "label": "syncCursor", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "expressionXY", "id": "def-common.XYChartProps.syncColors", diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index dec05d77bd487..705f353388259 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 158 | 0 | 148 | 9 | +| 159 | 0 | 149 | 9 | ## Client diff --git a/api_docs/expressions.devdocs.json b/api_docs/expressions.devdocs.json index dfc68e39dd9c9..651bca99eca7c 100644 --- a/api_docs/expressions.devdocs.json +++ b/api_docs/expressions.devdocs.json @@ -3716,7 +3716,7 @@ "id": "def-public.ExpressionRenderHandler.Unnamed.$2", "type": "Object", "tags": [], - "label": "{\n onRenderError,\n renderMode,\n syncColors,\n syncTooltips,\n interactive,\n hasCompatibleActions = async () => false,\n executionContext,\n }", + "label": "{\n onRenderError,\n renderMode,\n syncColors,\n syncTooltips,\n syncCursor,\n interactive,\n hasCompatibleActions = async () => false,\n executionContext,\n }", "description": [], "signature": [ "ExpressionRenderHandlerParams" @@ -7030,6 +7030,24 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-public.ExecutionContext.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [ + "\nReturns the state (true|false) of the sync cursor across panels switch." + ], + "signature": [ + "(() => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-public.ExecutionContext.isSyncTooltipsEnabled", @@ -10548,6 +10566,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "expressions", + "id": "def-public.IExpressionLoaderParams.syncCursor", + "type": "CompoundType", + "tags": [], + "label": "syncCursor", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/expressions/public/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "expressions", "id": "def-public.IExpressionLoaderParams.syncTooltips", @@ -10909,6 +10941,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-public.IInterpreterRenderHandlers.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-public.IInterpreterRenderHandlers.isSyncTooltipsEnabled", @@ -18009,6 +18057,24 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-server.ExecutionContext.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [ + "\nReturns the state (true|false) of the sync cursor across panels switch." + ], + "signature": [ + "(() => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-server.ExecutionContext.isSyncTooltipsEnabled", @@ -20583,6 +20649,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-server.IInterpreterRenderHandlers.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-server.IInterpreterRenderHandlers.isSyncTooltipsEnabled", @@ -29658,6 +29740,24 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-common.ExecutionContext.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [ + "\nReturns the state (true|false) of the sync cursor across panels switch." + ], + "signature": [ + "(() => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-common.ExecutionContext.isSyncTooltipsEnabled", @@ -31278,6 +31378,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "expressions", + "id": "def-common.ExpressionExecutionParams.syncCursor", + "type": "CompoundType", + "tags": [], + "label": "syncCursor", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/expressions/common/service/expressions_services.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "expressions", "id": "def-common.ExpressionExecutionParams.syncTooltips", @@ -34365,6 +34479,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "expressions", + "id": "def-common.IInterpreterRenderHandlers.isSyncCursorEnabled", + "type": "Function", + "tags": [], + "label": "isSyncCursorEnabled", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "expressions", "id": "def-common.IInterpreterRenderHandlers.isSyncTooltipsEnabled", diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index d1960b4de9b68..76c55a4b58037 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2183 | 17 | 1729 | 5 | +| 2191 | 17 | 1734 | 5 | ## Client diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 1133028869eba..da91f227af390 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 9c94a44ffadec..4523ead38b58b 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 9a9be7582ce9d..c0294e50ed582 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 76efd6cfb977f..d693b45a531aa 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index e58a20c5ee983..91ef5d2772ce2 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index c4c9a924f15bf..b989d9bad1e3b 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index e8b5280d0e2ea..8418d55c8ff85 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 246f650f020c1..4577b0f4e88dc 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 91cf3a7836f2c..6ecaeb0006d0d 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 7ee6cf44735d6..977ecfc0766f0 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 63e5474c9b3d2..c0dd3767e353d 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 75f7a54eb7483..49689351b17a9 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 4858834afb756..00352cab42857 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 6d7f73bfc8ad2..bdc594ed8725d 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index f03a1a6fa8165..908564cfc641c 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 0926dc4e419a0..1da5becf768bc 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 8ddcbeec02f9d..dd409bf5386d3 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index c491faf53cb8a..e0b8f3b9ff23f 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 59632c1d3a87d..bcc3a708b31e4 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index c9d7993a4df3d..1d8ae3a0f5c67 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index e5ca859ca6591..03683ffc81f4e 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index a49dcd7d53de9..db2e6330164d6 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index a112cef1f9ca5..f90ef47a7726b 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 14890706f4c7f..ec38943ba6b25 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 3d722227a9569..4a82106315395 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index d748be38bbb6c..f8b1e8255cbf6 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 2775628c8168e..5caf2591aac24 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 2af523b0462f1..227a50bcba7e0 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index f43771e589f42..4050ce85968e8 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 2589aa244318f..f0d4176e905e2 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index f3aa9c51bc4b6..1a43a15587640 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 939b2b88a6dc7..0a3d0a062b9ce 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 22bac5e77de6c..2e6937258bb59 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 8605fb4c27b84..a8a928b930d9f 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 7a386f010b42a..0b31a57545615 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index fb0e631dd6eeb..a6d305f92217c 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 9ed72653f94f9..7422e5e1610ad 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index c9f1bd5d5b1d1..636fc1a5bebae 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 39ca75ebdd662..406277b8006bd 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 65cbd40888647..5fbb43e9dae4e 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index a3833a17de3a6..a0db33ee20281 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 7979c5768713c..0dc8b453b2a6c 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index f1a06f92e296b..0bf53e2e5bae6 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index a28e66b152326..ff84d9fdc0503 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 3a2f44bf1236c..44c8aef5c9217 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 54dc5fd943387..17e0aa8eab477 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 4da9fffc75e8d..80b08fb8aba32 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 9aba2e6f2cfc8..cee02c9f7f6a3 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 7e5763b66db1e..c7710532f6c47 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 9090ea9b3dae4..238ce502f0c73 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 64ab097717304..92725a0d92687 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index a5f5aafb2ebc8..5582bcad413a2 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 4ad262feb7719..761e2dfe0b72b 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 606a1cb2b6a53..36c69cac69a0b 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 286c992389983..3c67cb607a218 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index cd2e9cc26d9d4..5fe6f62ef2929 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 0d172a3829c94..76f0c66049174 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 0435ca4ce5d88..eb3b83aac9b93 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 5b604e8925887..3c64a388200ad 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index a94a9afd70dd9..d54cea6fe899a 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 8be5b7c8766b1..4d11c278bce63 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index d2829bd75d504..ced77f8debe79 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 71770dfa6107a..063255c448d40 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index c242260d3ae9b..a163964a8177b 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 510745d909593..bbe5c1a7fb764 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 104b009e8e132..d0436a80628cb 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 88179af913545..74daa6b5a6aa2 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index e9f05e11af078..7134379ff167b 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index a8c8ffd2b89d8..805eb5e20cd76 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 3e7261b11c4f9..3089353641990 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index cf478de4599fd..c080da192d657 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 7171de6bc8257..5d760dc722338 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 1bbcbab54b3e5..0b033c3bf5a66 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 74c16cef96d37..a27ad888e8174 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index ee57062a1d770..076d1af298978 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index ca954ee656c72..13038f04466b3 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 686820b846c17..c3d8002cfde02 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index b371dc2ce6af3..9cdf49d635f1e 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 37e63190c4e6f..f8c2c116a9848 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 74ec3c2068ff3..c2f9f2219c782 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 312fa33dea490..756f1ec2a5301 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 09069175efcf2..c8e2693b97d0c 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 58af58b774bce..7a6b67f42ad3c 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index cd1c895ca79b4..82843d60e8a53 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index e6ac9fe853ede..b2c5d33b0964d 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 3b53f4ec9ab89..c79087990b7b0 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 05ab2714fde30..f8f2013e5beca 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 72033231812ec..36a0e5247908b 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 6e2fca747fbd4..889942cb35d08 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 3237999e37792..073d42a71ed8b 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 8e60ae8d13efc..75127c646b101 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 1557cc41e93cb..a868e5f82a6b1 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index a732c7b902574..76ac625a59b11 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 6d8dc337edd5c..3edf68eafe99d 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 21895582deb70..f707ec89e17b6 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 16426662fd83e..dc669daf91f77 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index cff15361430a5..3230a8e2bbaf1 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 3eca728a9128b..c56673e06cef2 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 7a0c2c59d2491..93bf87b306494 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index ac410e083924a..639d71c2d4594 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 97b824680cc3f..e1c52253dc8d1 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index d9e44f8020314..8aaa5fa4ba07b 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index aa5c36f61d8fd..2f876d13c3e17 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 392a6d628e97d..75217cafa2f59 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index b9dbfbc447c03..497a726e140a0 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 2d7375a3c7220..f534e0f28892b 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index fe3d8caa47c0f..d9383302da10c 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 118ae484900d1..61e50ad61f5c4 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 7bb0bc7a55924..ee66f0bfb4093 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 9058034fe6ed4..4a0c223679ec8 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 4129772acbce5..f9163546e7a0c 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index e1bc41b0b1fd0..93e16f5b7d558 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index a351162b92535..e2c122cf80066 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 80c67cbefb41d..0157435c53146 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 81c79f199e296..7a1162cc2155c 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 6cea0b3edb58b..4397611b84ba8 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 9528c7f087d4f..22bdcae2b8cea 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 1fc1b5edfd4a9..6bdc621187c53 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 95ffc3ff48c8a..4c77c0c54e9e9 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 596dfbfa9324f..0dd7400ad6ad5 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 0f49932a294e6..58ad84604a65f 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 8685b3dd8ffae..eeff94632ae1a 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 1b3a50a65001a..d4c79e0e6c215 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index a44aed5fb0c40..e82bbd8389273 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 5401b2238c84e..9db8ef993ee7c 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 8234e1c7699de..7245bd212d9f8 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index a254a39f50976..9bfa0261e6bf6 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 70fa1bdac381c..65ae87a11014b 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 8efcbe04147f2..c1d3dd3c41d4a 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index ae13deb6ab4a7..63d290d66b778 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 329a751558828..db4dbc041d411 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index b453f6bb2b57d..3b2067d95d659 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 426df918fb1c2..1ee60ba77c41f 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 267d37656f2d3..7b577e691950b 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index bdeef2478073c..ca3435f2f4d52 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index c8a131ca1c925..ed940e5483a3e 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 7052188237271..fe735e6c229f0 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index e29ec5c5f28cc..f54ad738ed7c1 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index bd9522fb6c16a..964a4762c74a3 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 166b281a1f819..21e6e4f1d3397 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 62a295a989748..312b838c9d7e1 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index b9b12f139a291..c608f300ad8e8 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index b9e17b56c7215..cb1d574e0a58c 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index c2d75d32460f5..62baf4d2d88d2 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index eeeab2680fc91..a691eb782e811 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 3b53b418fde0e..c10f9d65a6f71 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 7cd60fefcbed7..d574624b37f94 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 9bd5d2601c628..9525ea5d597d4 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index cb6aaa1892628..ff270c9571cce 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 997cbbbeee0ce..95ab433b8afb8 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index e8a96d95e0b52..0f3f1085f8c8a 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index ebb8890436531..a60490350a3ed 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 4e2e211290a68..e3fe63104244e 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 67ee330bf497e..0085619324578 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 12a6ae1b41c50..cab88970ed077 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 087f9bc2d6a84..76088f8aeed0a 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index b3ecdb125a1d8..fc5aed267b9f5 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 8920b923837be..2ec7dcbe4956b 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 4f8ee81478644..2484910018514 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 335fed85de068..b8c9e6c5557f1 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 9d39db8a256a8..4d6a9f502357d 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 8c860cc0ed201..0427e329d1011 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index ddae9cdc8613e..5cde88b3919e5 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 2590679c346ab..a5ea5d26f044f 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index e3e829c62749f..14efca2695a96 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 3aa81b6989235..5d8b628b0a600 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 93324103d7a72..5b768628e4650 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index dda5842f987e7..ed7469f8e97c8 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 2c23e50f95bce..290f19d278b55 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 6241b69a38c3d..340a6e14cf577 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 083c99ce18e9a..87365ac46488a 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 625e58764a98b..6bae1f5ae6d5f 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 5f38b9ffbe2f8..b112d2b576340 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 1a69a645a027b..6b8100a9b589f 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index e919b4aba9c51..78cec0e593b9c 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index e8913afa81c88..bfd62a7a6772c 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index c17dff7ee239c..2045467a8672e 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 6b9b7c47f66e3..7597dae0e37a3 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index dcbdcc38dfdb9..640ae9607d3b3 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 6fd8bc19e7e34..ac7d9d3c614be 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index bfc5286c8483b..ad7e34dec65b2 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 61702adbf85ec..59ba10b04be8b 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 5f4151126ff61..9dad230ca2bca 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index ed341b7fd0d3d..64208ee04c44c 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index dd99724236b57..e05772209caab 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 3ab75edf78427..a63c738302b0c 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index b8335686424f3..c7da7cfd52a0e 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 8c5befe03b359..72f9610185bf1 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 605bd1db95430..e3cf0863d2510 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 77f67be571740..6113655f9c767 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 0e63700233d85..7509afb9b1ae7 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index b2b1fa910efbc..a3bdf0e9100c6 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 9eb7c2fa89f3d..ee220a2445b3b 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 7a3a034993af1..c7cbab7cefb71 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 7461e140b1517..4e48fd41674ad 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 0d2aac1746d29..d19d29035f88e 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 232fe900144ad..6e19b9402bd68 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 703cc640f9c98..927a9e35f8957 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index ab550d01cd4aa..9a908f0df623b 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index f1a4c6333160c..25b904c350aa1 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 36bdaf020341d..0abeb8ab57c4a 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 9087b92760bf5..9fd9e68ba6614 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 62ce7e6a00a7a..68998444485e1 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index efc7e6717383e..785e8a58f6c04 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 6dde0c81a8b68..cba1aba4b8260 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 2b4e5883950e5..a7e679d18370c 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 4f66f7786e798..aa05bd60ae18a 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index ebb98ebacd44e..9449b5bac59f1 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 3d98ca7e00e92..f31a8eb027cc1 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index b1ca1bbb247b0..46ca6b388ba41 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 5d97e59fb4e81..840054b21257a 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index cc57923957615..3fe4d045d41dc 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 6a3a6ac4ef228..1a74dd508a738 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index aa2a7822c83c8..a868d5020cc5b 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 6131d1fcfce58..46f75db960ad2 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index b9a9606fa03d4..44687276f41fa 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 38886f7dae121..8d823a70a689c 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 07979c2656cfc..9acce86ac28e4 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index d369e769b38d7..19564c3aa8fa9 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 8e3e91f1da134..4ac66fcf327e1 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 237f0ef3a9024..49df6b1ff2c4f 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 8a0d54de39844..76f6d207b5225 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index d59e901750fc4..40bc459ae63ca 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index e990105e75989..9c20eddc8a232 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 1fb1dc646b831..babc0d4c61f6b 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 978b07b6bee0e..abfec62f04384 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index fbc0cca8a3a8e..75628505a8ea4 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 04d20b1704bd8..57e3ae6b223c9 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 6fd18e8011f86..0124e1b38a152 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index a8d86cfca2cfb..b8f39e86bdcba 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 584949a0b23a4..576e5be73b87e 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 88637f8423878..72684cd28d9e1 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index d38b83e89fcde..d5dc67c8edc67 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index e90e1e8c97e4a..f87f523d0b56a 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index fa5fe444a0276..f631ac324d1d0 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 41afd4e5fb4a0..9b0ae5c234b6a 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index a2837efbd4207..da5e941152a47 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index d4a8fc67beabd..62cfab54a06f5 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 87addb64d93e3..987efffb0f8ae 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 056b09bbb85cc..539d5ae582431 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 7ce61f34b4ab0..08c4ac78e3adb 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index cd60083336f7c..42c785435aef8 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 7d3de8e112faa..44e738d077c1f 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index c45e31b93fdb3..b1bbaa1796285 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index ffe79ed31b8f7..d9f38a49f975e 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 5ff8fb8885e7a..1e3bee65e9308 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 05d762a44ace5..7f4b52c6d311e 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 642072da18d1a..c4fb97f8e4fa5 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 91cb4417726a8..c317c380e6cd1 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index b915b9a086d46..b1f886993474c 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index f8ebff6ff0f35..40b4f6a029d7f 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 1f0ccc59a50e5..33ceaf49ecf75 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index a5b61d014aca9..a8c4b1e864210 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 3eeb2b8a1b4b7..b304f30777f3f 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index b78439042d011..eeaf3ec3f430c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 05e8f0fda3186..8eb1a4ff07c84 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 3c628af3d29db..fad9139f25596 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 180b30d640a55..c3099a7a51e10 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 67f2dcbf87d17..e7851ad78bed4 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 28fe4be1e9315..4433d4a820ef5 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index cd2bfe2727e29..6ea91ef49a072 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index b50866740f17e..c62dbdd1e83dc 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index d7e73919195c7..5185e64ae96c3 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index c4b979f0bf020..26d969e8de8e4 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 2fffdca031d68..406b564c37741 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 4f7505aa18f19..c42da58b607db 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index ef10794ec07c7..1e2b1a10306d2 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 4e445695ce043..c6cc3b55f1c9e 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 619317adad6ab..60ce680b77644 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 7c82fe28b9ef8..e1d98bcd2fb53 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index af25ac211f92c..621e5f1b4c3e5 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 02b67f55c2d11..04c1cde8832ca 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index a7e94ddd6bf9f..6b19c47dc1d47 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 520a84d725f50..cc85d61d46df9 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index e57378a0bdd1b..e8d9308bf5997 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 5848474c98abb..436e8bcce963b 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 34593f5e4de31..6c2a1c773c283 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 28ff056daa4d8..901c92404826c 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index c89a6bfd01217..d687ab10cb7a7 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index bb4d7a58c835d..98b6e73944f7a 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 836008a78b41d..725211e81d8a2 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 808ad6744bf6a..00ad67e879354 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 0953b950f3934..4467d33f0b409 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index b30a7490bcf3c..1e80c86ce5a31 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 7df2fce140900..ae0a544b7695f 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 2be9c46589362..7c8551ee4fc49 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 62bce0880f9f2..a2615f303483e 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 811a1eeae8e88..f5c420e0b3613 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 695c59da8b2dd..6b5285b485392 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 3108f06e328c4..5750c3e7538c2 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 285035a4d158d..d6d05446175c1 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -7219,6 +7219,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-public.XYChartProps.syncCursor", + "type": "boolean", + "tags": [], + "label": "syncCursor", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-public.XYChartProps.syncColors", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 705e405628d63..b6dbf8edb6768 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 658 | 0 | 567 | 45 | +| 659 | 0 | 568 | 45 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 46fdabc8e4ce4..b4dd33b05d466 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index f03ac62ef69d4..af33991449df5 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.devdocs.json b/api_docs/licensing.devdocs.json index 335c7891795d3..6b2d792de9c75 100644 --- a/api_docs/licensing.devdocs.json +++ b/api_docs/licensing.devdocs.json @@ -574,6 +574,14 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts" @@ -1839,6 +1847,14 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts" }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts" + }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts" diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 853896a42382a..a7707f7a483a7 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index ba4d095fe0776..c39127de230b9 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 32fbb57687eba..ff717f629fb87 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 379267cafc4e9..6843462849616 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 10e21a471b952..d99496f67b331 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 11aa6c1abad09..c3aa02065f24c 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index fc7fd5cb50030..e74ff2665332c 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 5713e1d3651b5..985a05b1bd793 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index e06ca6ebfca3d..d1a12bb52a8c4 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 641b1c39a2230..42652b4f681ec 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 4a4216ec894ca..c088a28c032a2 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -8054,7 +8054,7 @@ "label": "ObservabilityConfig", "description": [], "signature": [ - "{ readonly unsafe: Readonly<{} & { slo: Readonly<{} & { enabled: boolean; }>; alertDetails: Readonly<{} & { enabled: boolean; }>; }>; readonly annotations: Readonly<{} & { enabled: boolean; index: string; }>; }" + "{ readonly unsafe: Readonly<{} & { slo: Readonly<{} & { enabled: boolean; }>; alertDetails: Readonly<{} & { apm: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; uptime: Readonly<{} & { enabled: boolean; }>; }>; }>; readonly annotations: Readonly<{} & { enabled: boolean; index: string; }>; }" ], "path": "x-pack/plugins/observability/server/index.ts", "deprecated": false, diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 11f000f7d7608..aca18e6aa58ce 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 9fb829dcd0133..dab4536bed192 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 6e41a12b3f107..11a1a79ea8ab8 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,29 +15,29 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 488 | 405 | 38 | +| 489 | 406 | 38 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 32298 | 179 | 21765 | 1023 | +| 32374 | 179 | 21791 | 1023 | ## Plugin Directory | Plugin name           | Maintaining team | Description | API Cnt | Any Cnt | Missing
comments | Missing
exports | |--------------|----------------|-----------|--------------|----------|---------------|--------| -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 213 | 0 | 208 | 23 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 214 | 0 | 209 | 23 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 1 | 32 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 9 | 0 | 0 | 2 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 381 | 0 | 372 | 24 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 382 | 0 | 373 | 24 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 38 | 0 | 38 | 52 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 81 | 1 | 72 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Canvas application to Kibana | 9 | 0 | 8 | 3 | | | [ResponseOps](https://github.com/orgs/elastic/teams/response-ops) | The Case management system in Kibana | 87 | 0 | 70 | 28 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 264 | 2 | 249 | 9 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 34 | 0 | 26 | 0 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 39 | 0 | 11 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | Chat available on Elastic Cloud deployments for quicker assistance. | 1 | 0 | 0 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/@elastic/kibana-core) | Provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments. | 12 | 0 | 0 | 0 | | cloudFullStory | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | When Kibana runs on Elastic Cloud, this plugin registers FullStory as a shipper for telemetry. | 0 | 0 | 0 | 0 | @@ -48,7 +48,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2691 | 0 | 23 | 0 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 107 | 0 | 88 | 1 | -| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 120 | 0 | 113 | 3 | +| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 121 | 0 | 114 | 3 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 52 | 0 | 51 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3228 | 33 | 2516 | 24 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 16 | 0 | 7 | 0 | @@ -68,7 +68,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 106 | 0 | 106 | 10 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'error' renderer to expressions | 17 | 0 | 15 | 2 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Gauge plugin adds a `gauge` renderer and function to the expression plugin. The renderer will display the `gauge` chart. | 58 | 0 | 58 | 2 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 106 | 0 | 102 | 3 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 107 | 0 | 103 | 3 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'image' function and renderer to expressions | 26 | 0 | 26 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Adds a `metric` renderer and function to the expression plugin. The renderer will display the `legacy metric` chart. | 49 | 0 | 49 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'metric' function and renderer to expressions | 32 | 0 | 27 | 0 | @@ -78,8 +78,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'revealImage' function and renderer to expressions | 14 | 0 | 14 | 3 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'shape' function and renderer to expressions | 148 | 0 | 146 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Tagcloud plugin adds a `tagcloud` renderer and function to the expression plugin. The renderer will display the `Wordcloud` chart. | 7 | 0 | 7 | 0 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 158 | 0 | 148 | 9 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds expression runtime to Kibana | 2183 | 17 | 1729 | 5 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 159 | 0 | 149 | 9 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds expression runtime to Kibana | 2191 | 17 | 1734 | 5 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 222 | 0 | 95 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | @@ -104,7 +104,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 615 | 3 | 418 | 9 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 658 | 0 | 567 | 45 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 659 | 0 | 568 | 45 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -140,7 +140,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 249 | 0 | 90 | 0 | | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 55 | 0 | 54 | 23 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 7 | 0 | 7 | 1 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds URL Service and sharing capabilities to Kibana | 114 | 0 | 55 | 10 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds URL Service and sharing capabilities to Kibana | 115 | 0 | 56 | 10 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 22 | 1 | 22 | 1 | | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides the Spaces feature, which allows saved objects to be organized into meaningful categories. | 260 | 0 | 64 | 0 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 4 | 0 | 4 | 0 | @@ -159,6 +159,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 133 | 0 | 92 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 206 | 0 | 142 | 9 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 122 | 0 | 117 | 2 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 56 | 0 | 29 | 0 | | | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 131 | 2 | 104 | 17 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | urlDrilldown | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 2021d52d5b724..329f51e250d65 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index bd58024c8b8cf..0d9a7fc571f27 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index b8dfe036b8982..ae21bc28c6bf8 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 9d4b798faf065..37e12a3b07a9e 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index f378fa5d64b7b..4719a3c46b623 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index bd7cfb20966d9..bf157129468a4 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 92337b2109f81..35353d132c955 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 8a73ba883619c..e00e0f7d9a6fd 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 73ab7a4c9b93c..4ba0cc0ec3648 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index c1f7ee5147a7a..36af0dc877c5e 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 68f25f69466be..39ee9f7685854 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 9306b6f7fb5f0..ecd0f9604f7f1 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index eba3c945abc73..2769ab8cf6979 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index dc468637b642e..ec3131cb16134 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 3eb523a6b9ae3..e1961cfb6925f 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 7ca02cce627c9..a064cfbe7809c 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 24c4b236600d9..fbc1a6e18a359 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 4df85c4373c03..cd86553b2fdd2 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.devdocs.json b/api_docs/share.devdocs.json index 12c7ffc463d84..67996465a603c 100644 --- a/api_docs/share.devdocs.json +++ b/api_docs/share.devdocs.json @@ -1194,6 +1194,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "share", + "id": "def-public.ShowShareMenuOptions.snapshotShareWarning", + "type": "string", + "tags": [], + "label": "snapshotShareWarning", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/share/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "share", "id": "def-public.ShowShareMenuOptions.onClose", diff --git a/api_docs/share.mdx b/api_docs/share.mdx index c45c800a370a1..c30d5ac7213a7 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 114 | 0 | 55 | 10 | +| 115 | 0 | 56 | 10 | ## Client diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 0bedbd3ce8b4d..846371e932f14 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 32294e6a8ac26..1e28ebf3f6c31 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index cfdb1f16ae452..3d7d66d817877 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 38beb100ce9c7..36eb243de2cb7 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 6b05776dfe8d8..477dfacb56064 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index c7cbb53358e47..080140243e825 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index d4449150f82bc..44e1153ac923f 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 8ea2af4967e32..c76c8cd5fb369 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index bf761c3ba0bdd..7bc04081f6e9d 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index c9e7be99354d8..34fe439836dea 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 96864aac0ddf5..a0b552640a010 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 25c741ee70bf4..e38e33c757aaa 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 43b75995f580f..30c7e4602c598 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 82cf55203c9c8..d1908f8d512fd 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 1713f83d8f967..59ba7eadc46a1 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index efd048ac0e36e..d30517b185e1b 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.devdocs.json b/api_docs/unified_histogram.devdocs.json new file mode 100644 index 0000000000000..ae17302e9ef1e --- /dev/null +++ b/api_docs/unified_histogram.devdocs.json @@ -0,0 +1,1085 @@ +{ + "id": "unifiedHistogram", + "client": { + "classes": [], + "functions": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData", + "type": "Function", + "tags": [], + "label": "buildChartData", + "description": [ + "\nConvert the response from the chart request into a format that can be used\nby the unified histogram chart. The returned object should be used to update\n{@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}." + ], + "signature": [ + "({ data, dataView, timeInterval, response, }: { data: ", + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + }, + "; dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + "; timeInterval?: string | undefined; response?: ", + "SearchResponse", + "> | undefined; }) => { bucketInterval?: undefined; chartData?: undefined; } | { bucketInterval: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramBucketInterval", + "text": "UnifiedHistogramBucketInterval" + }, + " | undefined; chartData: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartData", + "text": "UnifiedHistogramChartData" + }, + "; }" + ], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData.$1", + "type": "Object", + "tags": [], + "label": "{\n data,\n dataView,\n timeInterval,\n response,\n}", + "description": [], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData.$1.data", + "type": "Object", + "tags": [], + "label": "data", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + } + ], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData.$1.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData.$1.timeInterval", + "type": "string", + "tags": [], + "label": "timeInterval", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.buildChartData.$1.response", + "type": "Object", + "tags": [], + "label": "response", + "description": [], + "signature": [ + "SearchResponse", + "> | undefined" + ], + "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.getChartAggConfigs", + "type": "Function", + "tags": [], + "label": "getChartAggConfigs", + "description": [ + "\nHelper function to get the agg configs required for the unified histogram chart request" + ], + "signature": [ + "({\n dataView,\n timeInterval,\n data,\n}: { dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + "; timeInterval: string; data: ", + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + }, + "; }) => ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.AggConfigs", + "text": "AggConfigs" + } + ], + "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.getChartAggConfigs.$1", + "type": "Object", + "tags": [], + "label": "{\n dataView,\n timeInterval,\n data,\n}", + "description": [], + "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.getChartAggConfigs.$1.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.getChartAggConfigs.$1.timeInterval", + "type": "string", + "tags": [], + "label": "timeInterval", + "description": [], + "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.getChartAggConfigs.$1.data", + "type": "Object", + "tags": [], + "label": "data", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + } + ], + "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayout", + "type": "Function", + "tags": [], + "label": "UnifiedHistogramLayout", + "description": [ + "\nA resizable layout component with two panels that renders a histogram with a hits\ncounter in the top panel, and a main display (data table, etc.) in the bottom panel.\nIf all context props are left undefined, the layout will render in a single panel\nmode including only the main display." + ], + "signature": [ + "React.ForwardRefExoticComponent<", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramLayoutProps", + "text": "UnifiedHistogramLayoutProps" + }, + " & React.RefAttributes<{}>>" + ], + "path": "src/plugins/unified_histogram/public/layout/index.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayout.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramBucketInterval", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramBucketInterval", + "description": [ + "\nThe bucketInterval object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.bucketInterval}" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramBucketInterval.scaled", + "type": "CompoundType", + "tags": [], + "label": "scaled", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramBucketInterval.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramBucketInterval.scale", + "type": "number", + "tags": [], + "label": "scale", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramChartContext", + "description": [ + "\nContext object for the chart" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [ + "\nThe fetch status of the chart request" + ], + "signature": [ + "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.hidden", + "type": "CompoundType", + "tags": [], + "label": "hidden", + "description": [ + "\nControls whether or not the chart is hidden" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.timeInterval", + "type": "string", + "tags": [], + "label": "timeInterval", + "description": [ + "\nControls the time interval of the chart" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.bucketInterval", + "type": "Object", + "tags": [], + "label": "bucketInterval", + "description": [ + "\nThe bucketInterval object returned by {@link buildChartData}" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramBucketInterval", + "text": "UnifiedHistogramBucketInterval" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.data", + "type": "Object", + "tags": [], + "label": "data", + "description": [ + "\nThe chartData object returned by {@link buildChartData}" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartData", + "text": "UnifiedHistogramChartData" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartContext.error", + "type": "Object", + "tags": [], + "label": "error", + "description": [ + "\nError from failed chart request" + ], + "signature": [ + "Error | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramChartData", + "description": [ + "\nThe chartData object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.data}" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.values", + "type": "Array", + "tags": [], + "label": "values", + "description": [], + "signature": [ + "{ x: number; y: number; }[]" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.xAxisOrderedValues", + "type": "Array", + "tags": [], + "label": "xAxisOrderedValues", + "description": [], + "signature": [ + "number[]" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.xAxisFormat", + "type": "Object", + "tags": [], + "label": "xAxisFormat", + "description": [], + "signature": [ + "{ id?: string | undefined; params?: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormatParams", + "text": "FieldFormatParams" + }, + "<{ pattern: string; }> | undefined; }" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.yAxisFormat", + "type": "Object", + "tags": [], + "label": "yAxisFormat", + "description": [], + "signature": [ + "{ id?: string | undefined; params?: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormatParams", + "text": "FieldFormatParams" + }, + "<{ pattern: string; }> | undefined; }" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.xAxisLabel", + "type": "string", + "tags": [], + "label": "xAxisLabel", + "description": [], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.yAxisLabel", + "type": "string", + "tags": [], + "label": "yAxisLabel", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramChartData.ordered", + "type": "Object", + "tags": [], + "label": "ordered", + "description": [], + "signature": [ + "Ordered" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramHitsContext", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramHitsContext", + "description": [ + "\nContext object for the hits count" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramHitsContext.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [ + "\nThe fetch status of the hits count request" + ], + "signature": [ + "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramHitsContext.total", + "type": "number", + "tags": [], + "label": "total", + "description": [ + "\nThe total number of hits" + ], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramLayoutProps", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramLayoutProps", + "text": "UnifiedHistogramLayoutProps" + }, + " extends { children?: React.ReactNode; }" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.className", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.services", + "type": "Object", + "tags": [], + "label": "services", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramServices", + "text": "UnifiedHistogramServices" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.hits", + "type": "Object", + "tags": [], + "label": "hits", + "description": [ + "\nContext object for the hits count -- leave undefined to hide the hits count" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramHitsContext", + "text": "UnifiedHistogramHitsContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.chart", + "type": "Object", + "tags": [], + "label": "chart", + "description": [ + "\nContext object for the chart -- leave undefined to hide the chart" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartContext", + "text": "UnifiedHistogramChartContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.resizeRef", + "type": "Object", + "tags": [], + "label": "resizeRef", + "description": [ + "\nRef to the element wrapping the layout which will be used for resize calculations" + ], + "signature": [ + "React.RefObject" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.topPanelHeight", + "type": "number", + "tags": [], + "label": "topPanelHeight", + "description": [ + "\nCurrent top panel height -- leave undefined to use the default" + ], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.appendHitsCounter", + "type": "Object", + "tags": [], + "label": "appendHitsCounter", + "description": [ + "\nAppend a custom element to the right of the hits count" + ], + "signature": [ + "React.ReactElement> | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTopPanelHeightChange", + "type": "Function", + "tags": [], + "label": "onTopPanelHeightChange", + "description": [ + "\nCallback to update the topPanelHeight prop when a resize is triggered" + ], + "signature": [ + "((topPanelHeight: number | undefined) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTopPanelHeightChange.$1", + "type": "number", + "tags": [], + "label": "topPanelHeight", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onEditVisualization", + "type": "Function", + "tags": [], + "label": "onEditVisualization", + "description": [ + "\nCallback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button" + ], + "signature": [ + "(() => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartHiddenChange", + "type": "Function", + "tags": [], + "label": "onChartHiddenChange", + "description": [ + "\nCallback to hide or show the chart -- should set {@link UnifiedHistogramChartContext.hidden} to chartHidden" + ], + "signature": [ + "((chartHidden: boolean) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartHiddenChange.$1", + "type": "boolean", + "tags": [], + "label": "chartHidden", + "description": [], + "signature": [ + "boolean" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTimeIntervalChange", + "type": "Function", + "tags": [], + "label": "onTimeIntervalChange", + "description": [ + "\nCallback to update the time interval -- should set {@link UnifiedHistogramChartContext.timeInterval} to timeInterval" + ], + "signature": [ + "((timeInterval: string) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTimeIntervalChange.$1", + "type": "string", + "tags": [], + "label": "timeInterval", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramServices", + "description": [ + "\nThe services required by the unified histogram components" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.data", + "type": "Object", + "tags": [], + "label": "data", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "public", + "docId": "kibDataPluginApi", + "section": "def-public.DataPublicPluginStart", + "text": "DataPublicPluginStart" + } + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.theme", + "type": "Object", + "tags": [], + "label": "theme", + "description": [], + "signature": [ + "{ readonly chartsDefaultTheme: ", + "RecursivePartial", + "<", + "Theme", + ">; readonly chartsDefaultBaseTheme: ", + "Theme", + "; chartsTheme$: ", + "Observable", + "<", + "RecursivePartial", + "<", + "Theme", + ">>; chartsBaseTheme$: ", + "Observable", + "<", + "Theme", + ">; readonly darkModeEnabled$: ", + "Observable", + "; useDarkMode: () => boolean; useChartsTheme: () => ", + "RecursivePartial", + "<", + "Theme", + ">; useChartsBaseTheme: () => ", + "Theme", + "; }" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.uiSettings", + "type": "Object", + "tags": [], + "label": "uiSettings", + "description": [], + "signature": [ + "IUiSettingsClient" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.fieldFormats", + "type": "CompoundType", + "tags": [], + "label": "fieldFormats", + "description": [], + "signature": [ + "Omit<", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormatsRegistry", + "text": "FieldFormatsRegistry" + }, + ", \"init\" | \"register\"> & { deserialize: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FormatFactory", + "text": "FormatFactory" + }, + "; }" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramFetchStatus", + "type": "Type", + "tags": [], + "label": "UnifiedHistogramFetchStatus", + "description": [ + "\nThe fetch status of a unified histogram request" + ], + "signature": [ + "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx new file mode 100644 index 0000000000000..a1d173ce94c7c --- /dev/null +++ b/api_docs/unified_histogram.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibUnifiedHistogramPluginApi +slug: /kibana-dev-docs/api/unifiedHistogram +title: "unifiedHistogram" +image: https://source.unsplash.com/400x175/?github +description: API docs for the unifiedHistogram plugin +date: 2022-10-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] +--- +import unifiedHistogramObj from './unified_histogram.devdocs.json'; + +The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. + +Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 56 | 0 | 29 | 0 | + +## Client + +### Functions + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index fadfe11b38fb7..76459a60c6d21 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index d799d4fd80c0e..a2e78fce5f760 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 0a52c11a03854..c39752fcb63b6 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index d82a3c180cad2..99ba0bda60c1d 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 59254e5f865e2..8ed7aa98ba363 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 0182afa67b39e..dbb08de964fc4 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 021eb298c7981..9bed30004b6cf 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 43257d5ca1b94..233daecf7a8b8 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index a78557b09236d..00b96cf306e06 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index dc90e0c203f09..e260c971f5579 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 9e617bff19342..a40a021d230e1 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index a65d89a8f19da..4b4d58a5ca996 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index ca2ffc9d904d8..7a757e85a52ad 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 2faa5d6c961d6..dd6fe5c32cdad 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index cd92c771a8660..b4661b0fa4f6e 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 5e76e91dfb780..e622d31cf22b1 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-10-17 +date: 2022-10-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 4853d859b371a..ac883c5518c7a 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -311,6 +311,10 @@ In general this plugin provides: |This Kibana plugin contains components and services for field list UI (as in fields sidebar on Discover and Lens pages). +|{kib-repo}blob/{branch}/src/plugins/unified_histogram/README.md[unifiedHistogram] +|The unifiedHistogram plugin provides UI components to create a layout including a resizable histogram and a main display. + + |{kib-repo}blob/{branch}/src/plugins/unified_search/README.md[unifiedSearch] |Contains all the components of Kibana's unified search experience. Specifically: diff --git a/docs/index-extra-title-page.html b/docs/index-extra-title-page.html index b70e3a985f22b..ced2737984fa5 100644 --- a/docs/index-extra-title-page.html +++ b/docs/index-extra-title-page.html @@ -4,8 +4,10 @@ get the most of your data.

- How-to videos -

+ What's new + Release notes + How-to videos +

@@ -17,27 +19,27 @@
  • - What is Kibana?
  • - Quick start
  • - Add data
  • - Create a dashboard
  • - Search your data
  • @@ -48,27 +50,27 @@
    • - Install Kibana
    • - Configure settings
    • - Kibana Query Language (KQL)
    • - Create a data view
    • - Create an alert
    • @@ -85,27 +87,27 @@
      • - Explore your data
      • - Create dashboards
      • - Create presentations
      • - Map geographic data
      • - Model, predict, and detect behavior
      • @@ -117,27 +119,27 @@
        • Secure access to Kibana
        • - Organize your data in spaces
        • - Categorize your saved objects
        • - Quickly find apps and objects
        • - Manage your data
        • diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc index e0e469c0d7d11..c59d2a612f2da 100644 --- a/docs/user/dashboard/dashboard.asciidoc +++ b/docs/user/dashboard/dashboard.asciidoc @@ -337,6 +337,8 @@ Apply a set of design options to the entire dashboard. * *Sync color pallettes across panels* — Applies the same color palette to all panels on the dashboard. +* *Sync cursor across panels* — When you hover your cursor over a *Lens*, *TSVB*, aggregation-based, or *Timelion* XY chart and a heatmap chart, the cursor on all other related dashboard charts automatically appear. + * *Sync tooltips across panels* — When you hover your cursor over a *Lens*, *TSVB*, aggregation-based, or *Timelion* XY chart, the tooltips on all other related dashboard charts automatically appear. [float] diff --git a/docs/user/dashboard/images/lens_advancedTutorial_numberOfCustomers_8.5.0.png b/docs/user/dashboard/images/lens_advancedTutorial_numberOfCustomers_8.5.0.png new file mode 100644 index 0000000000000..ec3085da63653 Binary files /dev/null and b/docs/user/dashboard/images/lens_advancedTutorial_numberOfCustomers_8.5.0.png differ diff --git a/docs/user/dashboard/images/lens_areaPercentageNumberOfOrdersByCategory_7.16.png b/docs/user/dashboard/images/lens_areaPercentageNumberOfOrdersByCategory_7.16.png deleted file mode 100644 index 6addc8bc276e9..0000000000000 Binary files a/docs/user/dashboard/images/lens_areaPercentageNumberOfOrdersByCategory_7.16.png and /dev/null differ diff --git a/docs/user/dashboard/images/lens_layerActions_8.5.0.png b/docs/user/dashboard/images/lens_layerActions_8.5.0.png new file mode 100644 index 0000000000000..ca8a92a36cded Binary files /dev/null and b/docs/user/dashboard/images/lens_layerActions_8.5.0.png differ diff --git a/docs/user/dashboard/lens-advanced.asciidoc b/docs/user/dashboard/lens-advanced.asciidoc index 04822444c530e..d89236b538eda 100644 --- a/docs/user/dashboard/lens-advanced.asciidoc +++ b/docs/user/dashboard/lens-advanced.asciidoc @@ -57,13 +57,15 @@ image::images/lens_clickAndDragZoom_7.16.gif[Cursor clicking and dragging across . In the layer pane, click *Count of Records*. -.. In the *Name* field, enter `Number of orders`. - -.. Click *Add advanced options > Normalize by unit*. +.. Click *Advanced*. .. From the *Normalize by unit* dropdown, select *per hour*, then click *Close*. + -*Normalize unit* converts *Average sales per 12 hours* into *Average sales per 12 hours (per hour)* by dividing the number of hours. +*Normalize by unit* converts `Count of Records` into `Count of records per hour` by dividing by 24. + +.. In the *Name* field, enter `Number of orders`. + +.. Click *Close*. . To hide the *Horizontal axis* label, open the *Bottom Axis* menu, then select *None* from the *Axis title* dropdown. @@ -73,13 +75,13 @@ To identify the 75th percentile of orders, add a reference line: . Click *Static value*. -.. Click *Quick functions*, then click *Percentile*. +.. Click *Quick function*, then click *Percentile*. .. From the *Field* dropdown, select *total_quantity*. -.. In the *Percentile* field, enter `75`. +.. In the *Reference line value* field, enter `75`. -. Configure the display options. +. Configure the *Appearance* options. .. In the *Name* field, enter `75th`. @@ -168,9 +170,11 @@ Add a layer to display the customer traffic: .. In the *Name* field, enter `Number of customers`. -.. In the *Series color* field, enter *#D36086*. +.. In the *Series color* field, enter `#D36086`. .. Click *Right* for the *Axis side*, then click *Close*. ++ +image::images/lens_advancedTutorial_numberOfCustomers_8.5.0.png[Number of customers area chart in Lens] . From the *Available fields* list, drag *order_date* to the *Horizontal Axis* field in the second layer. @@ -202,7 +206,7 @@ To view change over time as a percentage, create an *Area percentage* chart that For each order category, create a filter: -. In the layer pane, click *Add or drag-and-drop a field* for *Break down by*. +. In the layer pane, click *Add or drag-and-drop a field* for *Breakdown*. . Click the *Filters* function. @@ -255,7 +259,7 @@ Configure the cumulative sum of store orders: Filter the results to display the data for only Saturday and Sunday: -. In the layer pane, click *Add or drag-and-drop a field* for *Break down by*. +. In the layer pane, click *Add or drag-and-drop a field* for *Breakdown*. . Click the *Filters* function. @@ -294,7 +298,7 @@ To create a week-over-week comparison, shift *Count of Records [1]* by one week: . In the layer pane, click *Count of Records [1]*. -. Click *Add advanced options > Time shift*, select *1 week ago*, then click *Close*. +. Click *Advanced*, select *1 week ago* from the *Time shift* dropdown, then click *Close*. + To use custom time shifts, enter the time value and increment, then press Enter. For example, enter *1w* to use the *1 week ago* time shift. + @@ -322,9 +326,11 @@ To compare time range changes as a percent, create a bar chart that compares the . Click *Formula*, then enter `count() / count(shift='1w') - 1`. -. Open the *Value format* dropdown, select *Percent*, then enter `0` in the *Decimals* field. +. In the *Name* field, enter `Percent of change`. -. In the *Name* field, enter `Percent of change`, then click *Close*. +. From the *Value format* dropdown, select *Percent*, then enter `0` in the *Decimals* field. + +. Click *Close*. + [role="screenshot"] image::images/lens_percent_chage.png[Bar chart with percent change in sales between the current time and the previous week] @@ -359,7 +365,7 @@ Create a date histogram table and group the customer count metric by category, s To split the metric, add columns for each continent using the *Columns* field: -. From the *Available fields* list, drag *geoip.continent_name* to the *Columns* field in the layer pane. +. From the *Available fields* list, drag *geoip.continent_name* to the *Split metrics by* field in the layer pane. + [role="screenshot"] image::images/lens_table_over_time.png[Date histogram table with groups for the customer count metric] diff --git a/docs/user/dashboard/lens.asciidoc b/docs/user/dashboard/lens.asciidoc index 80e1665753c15..6c695cd3a74a9 100644 --- a/docs/user/dashboard/lens.asciidoc +++ b/docs/user/dashboard/lens.asciidoc @@ -15,21 +15,6 @@ With *Lens*, you can: * Use time shifts to compare the data in two time intervals, such as month over month. * Add annotations and reference lines. - -++++ - - -
          -++++ - [float] [[create-the-visualization-panel]] ==== Create visualizations @@ -50,7 +35,7 @@ Choose the data you want to visualize. . If you want to learn more about the data a field contains, click the field. -. To visualize more than one {data-source}, click *Add layer > Visualization*, then select the {data-source}. +. To visualize more than one {data-source}, click *Add layer*, select the layer type, then select the {data-source}. Edit and delete. @@ -58,6 +43,10 @@ Edit and delete. . To delete a field, close the configuration options, then click *X* next to the field. +. To clone a layer, click image:dashboard/images/lens_layerActions_8.5.0.png[Actions menu to duplicate Lens visualization layers] in the layer pane, then select *Duplicate layer*. + +. To clear the layer configuration, click image:dashboard/images/lens_layerActions_8.5.0.png[Actions menu to clear Lens visualization layers] in the layer pane, then select *Clear layer*. + TIP: You can manually apply the changes you make, which is helpful when creating large and complex visualizations. To manually apply your changes, click *Settings* in the toolbar, then deselect *Auto-apply visualization changes*. [float] @@ -95,12 +84,16 @@ All columns that belong to the same layer pane group are sorted in the table. * *Name* — Specifies the field display name. +* *Collapse by* — Aggregates all metric values with the same value into a single number. + * *Value format* — Specifies how the field value displays in the table. * *Text alignment* — Aligns the values in the cell to the *Left*, *Center*, or *Right*. * *Hide column* — Hides the column for the field. +* *Directly filter on click* — Turns column values into clickable links that allow you to filter or drill down into the data. + * *Summary row* — Adds a row that displays the summary value. When specified, allows you to enter a *Summary label*. * *Color by value* — Applies color to the cell or text values. To change the color, click *Edit*. @@ -169,13 +162,13 @@ TIP: For detailed information on formulas, click image:dashboard/images/formula_ [[compare-data-with-time-offsets]] ==== Compare differences over time -Compare your real-time data set to the results that are offset by a time increment. For example, you can compare the real-time percentage of a user CPU time spent to the results offset by one hour. +Compare your real-time data to the results that are offset by a time increment. For example, you can compare the real-time percentage of a user CPU time spent to the results offset by one hour. . In the layer pane, click the field you want to offset. -. From the *Add advanced options* dropdown, select *Time shift*. +. Click *Advanced*. -. Select the time offset increment. +. In the *Time shift* field, enter the time offset increment. For a time shift example, refer to <>. @@ -185,13 +178,15 @@ For a time shift example, refer to <>. preview::[] -Annotations allow you to call out specific points in your visualizations that are important, such as a major change in the data. You can add text and icons to annotations and customize the appearance, such as the line format and color. +Annotations allow you to call out specific points in your visualizations that are important, such as a major change in the data. You can add annotations for any {data-source}, add text and icons, specify the line format and color, and more. [role="screenshot"] image::images/lens_annotations_8.2.0.png[Lens annotations] . In the layer pane, click *Add layer > Annotations*. +. Select the {data-source}. + . To open the annotation options, click *Event*. . Specify the *Annotation date*. @@ -202,7 +197,7 @@ image::images/lens_annotations_8.2.0.png[Lens annotations] . Change the *Appearance* options for how you want the annotation to display. -. Click *Close*. +. To close, click *X*. [float] [[add-reference-lines]] diff --git a/docs/user/dashboard/tsvb.asciidoc b/docs/user/dashboard/tsvb.asciidoc index 07bb653af9750..d9cd137978e9c 100644 --- a/docs/user/dashboard/tsvb.asciidoc +++ b/docs/user/dashboard/tsvb.asciidoc @@ -134,9 +134,9 @@ The *Markdown* visualization supports Markdown with Handlebar (mustache) syntax [float] [[edit-visualizations-in-lens]] -==== Edit visualizations in Lens +==== Open and edit TSVB visualizations in Lens -Open and edit your Time Series *TSVB* visualizations in *Lens*, which is the drag-and-drop visualization editor that provides you with additional visualization types, reference lines, and more. +Open and edit Time Series and Top N *TSVB* visualizations in *Lens*. When you open *TSVB* visualizations in *Lens*, all configuration options and annotations appear in the *Lens* visualization editor. To get started, click *Edit visualization in Lens* in the toolbar. diff --git a/packages/analytics/shippers/elastic_v3/server/README.md b/packages/analytics/shippers/elastic_v3/server/README.md index ccdcf6a66cbe2..edb4bdffa0dba 100644 --- a/packages/analytics/shippers/elastic_v3/server/README.md +++ b/packages/analytics/shippers/elastic_v3/server/README.md @@ -22,4 +22,4 @@ analytics.registerShipper(ElasticV3ServerShipper, { channelName: 'myChannel', ve ## Transmission protocol -This shipper sends the events to the Elastic Internal Telemetry Service. It holds up to 1000 events in a shared queue. Any additional incoming events once it's full will be dropped. It sends the events from the queue in batches of 10kB every 10 seconds. If not enough events are available in the queue for longer than 10 minutes, it will send any remaining events. When shutting down, it'll send all the remaining events in the queue. +This shipper sends the events to the Elastic Internal Telemetry Service. It holds up to 1000 events in a shared queue. Any additional incoming events once it's full will be dropped. It sends the events from the queue in batches of up to 10kB every 10 seconds. When shutting down, it'll send all the remaining events in the queue. diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts index 668574dbb8f1d..03356f7428da7 100644 --- a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts +++ b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts @@ -117,13 +117,13 @@ describe('ElasticV3ServerShipper', () => { ); test( - 'calls to reportEvents call `fetch` after 10 minutes when optIn value is set to true', + 'calls to reportEvents call `fetch` after 10 seconds when optIn value is set to true', fakeSchedulers(async (advance) => { shipper.reportEvents(events); shipper.optIn(true); const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenCalledWith( 'https://telemetry-staging.elastic.co/v3/send/test-channel', { @@ -150,12 +150,12 @@ describe('ElasticV3ServerShipper', () => { ); test( - 'calls to reportEvents do not call `fetch` after 10 minutes when optIn value is set to false', + 'calls to reportEvents do not call `fetch` after 10 seconds when optIn value is set to false', fakeSchedulers((advance) => { shipper.reportEvents(events); shipper.optIn(false); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).not.toHaveBeenCalled(); }) ); @@ -201,8 +201,8 @@ describe('ElasticV3ServerShipper', () => { shipper['firstTimeOffline'] = null; shipper.reportEvents(events); shipper.optIn(true); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenCalledWith( 'https://telemetry-staging.elastic.co/v3/send/test-channel', { @@ -226,11 +226,11 @@ describe('ElasticV3ServerShipper', () => { shipper.reportEvents(new Array(1000).fill(events[0])); shipper.optIn(true); - // Due to the size of the test events, it matches 9 rounds. + // Due to the size of the test events, it matches 8 rounds. for (let i = 0; i < 9; i++) { const counter = firstValueFrom(shipper.telemetryCounter$); setLastBatchSent(Date.now() - 10 * SECONDS); - advance(10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenNthCalledWith( i + 1, 'https://telemetry-staging.elastic.co/v3/send/test-channel', @@ -277,8 +277,8 @@ describe('ElasticV3ServerShipper', () => { shipper.reportEvents(events); shipper.optIn(true); const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenCalledWith( 'https://telemetry-staging.elastic.co/v3/send/test-channel', { @@ -315,8 +315,8 @@ describe('ElasticV3ServerShipper', () => { shipper.reportEvents(events); shipper.optIn(true); const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenCalledWith( 'https://telemetry-staging.elastic.co/v3/send/test-channel', { @@ -458,8 +458,8 @@ describe('ElasticV3ServerShipper', () => { shipper.reportEvents(events); shipper.optIn(true); const counter = firstValueFrom(shipper.telemetryCounter$); - setLastBatchSent(Date.now() - 10 * MINUTES); - advance(10 * MINUTES); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(1 * SECONDS); // Moving 1 second should be enough to trigger the logic expect(fetchMock).toHaveBeenNthCalledWith( 1, 'https://telemetry-staging.elastic.co/v3/send/test-channel', diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts index e8cb3c7bff5db..34ebe134adcf7 100644 --- a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts +++ b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts @@ -12,10 +12,7 @@ import { Subject, ReplaySubject, interval, - concatMap, merge, - from, - firstValueFrom, timer, retryWhen, tap, @@ -24,6 +21,7 @@ import { map, BehaviorSubject, exhaustMap, + mergeMap, } from 'rxjs'; import type { AnalyticsClientInitContext, @@ -46,6 +44,7 @@ const MINUTE = 60 * SECOND; const HOUR = 60 * MINUTE; const KIB = 1024; const MAX_NUMBER_OF_EVENTS_IN_INTERNAL_QUEUE = 1000; +const MIN_TIME_SINCE_LAST_SEND = 10 * SECOND; /** * Elastic V3 shipper to use on the server side. @@ -130,6 +129,7 @@ export class ElasticV3ServerShipper implements IShipper { * @param events batched events {@link Event} */ public reportEvents(events: Event[]) { + // If opted out OR offline for longer than 24 hours, skip processing any events. if ( this.isOptedIn$.value === false || (this.firstTimeOffline && Date.now() - this.firstTimeOffline > 24 * HOUR) @@ -216,42 +216,40 @@ export class ElasticV3ServerShipper implements IShipper { } private setInternalSubscriber() { - // Check the status of the queues every 1 second. + // Create an emitter that emits when MIN_TIME_SINCE_LAST_SEND have passed since the last time we sent the data + const minimumTimeSinceLastSent$ = interval(SECOND).pipe( + filter(() => Date.now() - this.lastBatchSent >= MIN_TIME_SINCE_LAST_SEND) + ); + merge( - interval(1000).pipe(takeUntil(this.shutdown$)), - // Using a promise because complete does not emit through the pipe. - from(firstValueFrom(this.shutdown$, { defaultValue: true })) + minimumTimeSinceLastSent$.pipe( + takeUntil(this.shutdown$), + map(() => ({ shouldFlush: false })) + ), + // Attempt to send one last time on shutdown, flushing the queue + this.shutdown$.pipe(map(() => ({ shouldFlush: true }))) ) .pipe( - // Only move ahead if it's opted-in and online. - filter(() => this.isOptedIn$.value === true && this.firstTimeOffline === null), - - // Send the events now if (validations sorted from cheapest to most CPU expensive): - // - We are shutting down. - // - There are some events in the queue, and we didn't send anything in the last 10 minutes. - // - The last time we sent was more than 10 seconds ago and: - // - We reached the minimum batch size of 10kB per request in our leaky bucket. - // - The queue is full (meaning we'll never get to 10kB because the events are very small). + // Only move ahead if it's opted-in and online, and there are some events in the queue filter( () => - (this.internalQueue.length > 0 && - (this.shutdown$.isStopped || Date.now() - this.lastBatchSent >= 10 * MINUTE)) || - (Date.now() - this.lastBatchSent >= 10 * SECOND && - (this.internalQueue.length === MAX_NUMBER_OF_EVENTS_IN_INTERNAL_QUEUE || - this.getQueueByteSize(this.internalQueue) >= 10 * KIB)) + this.isOptedIn$.value === true && + this.firstTimeOffline === null && + this.internalQueue.length > 0 ), // Send the events: // 1. Set lastBatchSent and retrieve the events to send (clearing the queue) in a synchronous operation to avoid race conditions. - map(() => { + map(({ shouldFlush }) => { this.lastBatchSent = Date.now(); - return this.getEventsToSend(); + return this.getEventsToSend(shouldFlush); }), - // 2. Skip empty buffers + // 2. Skip empty buffers (just to be sure) filter((events) => events.length > 0), // 3. Actually send the events - // Using `concatMap` here because we want to send events whenever the emitter says so. Otherwise, it'd skip sending some events. - concatMap(async (eventsToSend) => await this.sendEvents(eventsToSend)) + // Using `mergeMap` here because we want to send events whenever the emitter says so: + // We don't want to skip emissions (exhaustMap) or enqueue them (concatMap). + mergeMap((eventsToSend) => this.sendEvents(eventsToSend)) ) .subscribe(); } @@ -278,13 +276,13 @@ export class ElasticV3ServerShipper implements IShipper { } /** - * Returns a queue of events of up-to 10kB. + * Returns a queue of events of up-to 10kB. Or all events in the queue if it's a FLUSH action. * @remarks It mutates the internal queue by removing from it the events returned by this method. * @private */ - private getEventsToSend(): Event[] { - // If the internal queue is already smaller than the minimum batch size, do a direct assignment. - if (this.getQueueByteSize(this.internalQueue) < 10 * KIB) { + private getEventsToSend(shouldFlush: boolean): Event[] { + // If the internal queue is already smaller than the minimum batch size, or it's a flush action, do a direct assignment. + if (shouldFlush || this.getQueueByteSize(this.internalQueue) < 10 * KIB) { return this.internalQueue.splice(0, this.internalQueue.length); } // Otherwise, we'll feed the events to the leaky bucket queue until we reach 10kB. diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 07d813b5f6dc8..5b96ef213bf3e 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -49,7 +49,7 @@ pageLoadAssetSize: expressions: 140958 expressionShape: 34008 expressionTagcloud: 27505 - expressionXY: 38000 + expressionXY: 38500 features: 21723 fieldFormats: 65209 files: 22673 @@ -122,6 +122,7 @@ pageLoadAssetSize: uiActions: 35121 uiActionsEnhanced: 38494 unifiedFieldList: 65500 + unifiedHistogram: 19928 unifiedSearch: 71059 upgradeAssistant: 81241 urlDrilldown: 30063 diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index f6591cf7a7759..7dce76528a5a0 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -130,7 +130,7 @@ describe('checking migration metadata changes on all registered SO types', () => "siem-ui-timeline-pinned-event": "e2697b38751506c7fce6e8b7207a830483dc4283", "space": "c4a0acce1bd4b9cce85154f2a350624a53111c59", "spaces-usage-stats": "922d3235bbf519e3fb3b260e27248b1df8249b79", - "synthetics-monitor": "cffb4dfe9e0a36755a226d5cf983c21aac2b5b1e", + "synthetics-monitor": "7bebb6511c70359386f9e20c982db86259c7915c", "synthetics-privates-locations": "dd00385f4a27ef062c3e57312eeb3799872fa4af", "tag": "39413f4578cc2128c9a0fda97d0acd1c8862c47a", "task": "ef53d0f070bd54957b8fe22fae3b1ff208913f76", diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index e0a9171e52169..ff13005aaf922 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -298,7 +298,10 @@ kibana_vars=( xpack.ingestManager.registryUrl xpack.observability.annotations.index xpack.observability.unsafe.slo.enabled - xpack.observability.unsafe.alertDetails.enabled + xpack.observability.unsafe.alertDetails.apm.enabled + xpack.observability.unsafe.alertDetails.metrics.enabled + xpack.observability.unsafe.alertDetails.logs.enabled + xpack.observability.unsafe.alertDetails.uptime.enabled xpack.reporting.capture.browser.autoDownload xpack.reporting.capture.browser.chromium.disableSandbox xpack.reporting.capture.browser.chromium.inspect diff --git a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap index 8e84b2c8e22a8..96b70e33021f4 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/__snapshots__/heatmap_function.test.ts.snap @@ -101,6 +101,7 @@ Object { ], "type": "datatable", }, + "syncCursor": true, "syncTooltips": false, }, } diff --git a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts index 76ea0f30ac26b..548d4ec0ab49e 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/expression_functions/heatmap_function.ts @@ -231,6 +231,7 @@ export const heatmapFunction = (): HeatmapExpressionFunctionDefinition => ({ handlers.getExecutionContext?.()?.description, }, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, + syncCursor: handlers?.isSyncCursorEnabled?.() ?? true, }, }; }, diff --git a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts index c3db9e34394a3..5aa1507f30b03 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts @@ -93,6 +93,7 @@ export interface HeatmapExpressionProps { data: Datatable; args: HeatmapArguments; syncTooltips: boolean; + syncCursor: boolean; } export interface HeatmapRender { diff --git a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_renderers.ts b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_renderers.ts index c8763903a3927..b59a8ee2c5166 100644 --- a/src/plugins/chart_expressions/expression_heatmap/common/types/expression_renderers.ts +++ b/src/plugins/chart_expressions/expression_heatmap/common/types/expression_renderers.ts @@ -39,5 +39,6 @@ export type HeatmapRenderProps = HeatmapExpressionProps & { uiState: PersistedState; interactive: boolean; syncTooltips: boolean; + syncCursor: boolean; renderComplete: IInterpreterRenderHandlers['done']; }; diff --git a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.test.tsx b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.test.tsx index fa4b58dd89deb..4720e9025d63d 100644 --- a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.test.tsx +++ b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.test.tsx @@ -125,6 +125,7 @@ describe('HeatmapComponent', function () { formatFactory: formatService.deserialize, interactive: true, syncTooltips: false, + syncCursor: true, renderComplete: jest.fn(), }; }); diff --git a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx index 64d7e4d03a46d..399d653e0b4b6 100644 --- a/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx +++ b/src/plugins/chart_expressions/expression_heatmap/public/components/heatmap_component.tsx @@ -146,6 +146,7 @@ export const HeatmapComponent: FC = memo( uiState, interactive, syncTooltips, + syncCursor, renderComplete, }) => { const chartRef = useRef(null); @@ -576,7 +577,7 @@ export const HeatmapComponent: FC = memo( noResults={ } - onPointerUpdate={handleCursorUpdate} + onPointerUpdate={syncCursor ? handleCursorUpdate : undefined} externalPointerEvents={{ tooltip: { visible: syncTooltips }, }} diff --git a/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx b/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx index 744d5d49f9376..4b813fb93416f 100644 --- a/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx +++ b/src/plugins/chart_expressions/expression_heatmap/public/expression_renderers/heatmap_renderer.tsx @@ -90,6 +90,7 @@ export const heatmapRenderer: ( interactive={isInteractive()} chartsActiveCursorService={plugins.charts.activeCursor} syncTooltips={config.syncTooltips} + syncCursor={config.syncCursor} />
      , diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.test.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.test.ts index 3976f6977e2be..eae70ea54f0c9 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.test.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis.test.ts @@ -28,6 +28,7 @@ describe('layeredXyVis', () => { args: { ...rest, layers: [sampleExtendedLayer] }, syncColors: false, syncTooltips: false, + syncCursor: true, canNavigateToLens: false, }, }); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts index d6553ef3dd7b3..305c6c2ee6496 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/layered_xy_vis_fn.ts @@ -64,6 +64,7 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) canNavigateToLens: Boolean(handlers.variables.canNavigateToLens), syncColors: handlers?.isSyncColorsEnabled?.() ?? false, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, + syncCursor: handlers?.isSyncCursorEnabled?.() ?? true, }, }; }; diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts index a09c5f05adb08..90710b945c763 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis.test.ts @@ -41,6 +41,7 @@ describe('xyVis', () => { canNavigateToLens: false, syncColors: false, syncTooltips: false, + syncCursor: true, }, }); }); @@ -350,6 +351,7 @@ describe('xyVis', () => { canNavigateToLens: false, syncColors: false, syncTooltips: false, + syncCursor: true, }, }); }); diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index 849f2030a4697..f7577efc45b86 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -139,6 +139,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { canNavigateToLens: Boolean(handlers.variables.canNavigateToLens), syncColors: handlers?.isSyncColorsEnabled?.() ?? false, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, + syncCursor: handlers?.isSyncCursorEnabled?.() ?? true, }, }; }; diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts index 94567f563cdb1..0b65347192106 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts @@ -17,6 +17,7 @@ import { XYProps } from './expression_functions'; export interface XYChartProps { args: XYProps; syncTooltips: boolean; + syncCursor: boolean; syncColors: boolean; canNavigateToLens?: boolean; } diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx index e7b109b65abcc..b6777d36c1d9e 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.test.tsx @@ -117,6 +117,7 @@ describe('XYChart component', () => { onSelectRange, syncColors: false, syncTooltips: false, + syncCursor: true, useLegacyTimeAxis: false, eventAnnotationService: eventAnnotationServiceMock, renderComplete: jest.fn(), diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 0d88480b00342..240c4e182d43e 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -125,6 +125,7 @@ export type XYChartRenderProps = Omit & { renderMode: RenderMode; syncColors: boolean; syncTooltips: boolean; + syncCursor: boolean; eventAnnotationService: EventAnnotationServiceType; renderComplete: () => void; uiState?: PersistedState; @@ -199,6 +200,7 @@ export function XYChart({ interactive = true, syncColors, syncTooltips, + syncCursor, useLegacyTimeAxis, renderComplete, uiState, @@ -753,7 +755,7 @@ export function XYChart({ /> } onRenderChange={onRenderChange} - onPointerUpdate={handleCursorUpdate} + onPointerUpdate={syncCursor ? handleCursorUpdate : undefined} externalPointerEvents={{ tooltip: { visible: syncTooltips, placement: Placement.Right }, }} diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index e00f5b04bd590..085cf9b8c7bb8 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -235,6 +235,7 @@ export const getXyChartRenderer = ({ renderMode={handlers.getRenderMode()} syncColors={config.syncColors} syncTooltips={config.syncTooltips} + syncCursor={config.syncCursor} uiState={handlers.uiState as PersistedState} renderComplete={renderComplete} /> diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/interval.test.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/interval.test.ts index 71d12db8ffb91..db424238bcffb 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/interval.test.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/interval.test.ts @@ -18,7 +18,12 @@ describe('calculateMinInterval', () => { beforeEach(() => { const { layers, ...restArgs } = sampleArgs().args; - xyProps = { args: { ...restArgs, layers }, syncColors: false, syncTooltips: false }; + xyProps = { + args: { ...restArgs, layers }, + syncColors: false, + syncTooltips: false, + syncCursor: true, + }; layer = xyProps.args.layers[0] as DataLayerConfig; layer.xScaleType = 'time'; }); diff --git a/src/plugins/charts/public/static/components/endzones.tsx b/src/plugins/charts/public/static/components/endzones.tsx index 727004993d171..e89ec60fd5a8b 100644 --- a/src/plugins/charts/public/static/components/endzones.tsx +++ b/src/plugins/charts/public/static/components/endzones.tsx @@ -16,8 +16,9 @@ import { RectAnnotationStyle, } from '@elastic/charts'; import { i18n } from '@kbn/i18n'; -import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, useEuiTheme } from '@elastic/eui'; import { euiLightVars as lightEuiTheme, euiDarkVars as darkEuiTheme } from '@kbn/ui-theme'; +import { css } from '@emotion/react'; interface EndzonesProps { isDarkMode: boolean; @@ -141,19 +142,22 @@ const partialDataText = i18n.translate('charts.partialData.bucketTooltipText', { 'The selected time range does not include this entire bucket. It might contain partial data.', }); -const Prompt = () => ( - - - - - {partialDataText} - -); +const Prompt = () => { + const { euiTheme } = useEuiTheme(); + const headerPartialCss = css` + font-weight: ${euiTheme.font.weight.regular}; + min-width: ${euiTheme.base * 12}; + `; + + return ( + + + + + {partialDataText} + + ); +}; export const renderEndzoneTooltip = ( diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index d4ee045a8d9a8..a5f6ab4197bd9 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -68,6 +68,7 @@ export interface InheritedChildInput extends IndexSignature { id: string; searchSessionId?: string; syncColors?: boolean; + syncCursor?: boolean; syncTooltips?: boolean; executionContext?: KibanaExecutionContext; } @@ -351,6 +352,7 @@ export class DashboardContainer extends Container; } /** @@ -102,13 +102,15 @@ const filtersAreEqual = (first: Filter, second: Filter) => */ export const stateToRawDashboardState = ({ state, -}: StateToRawDashboardStateProps): RawDashboardState => { +}: StateToRawDashboardStateProps): Partial => { const { initializerContext: { kibanaVersion }, } = pluginServices.getServices(); - const savedDashboardPanels = Object.values(state.panels).map((panel) => - convertPanelStateToSavedDashboardPanel(panel, kibanaVersion) - ); - return { ...omit(state, 'panels'), panels: savedDashboardPanels }; + const savedDashboardPanels = state?.panels + ? Object.values(state.panels).map((panel) => + convertPanelStateToSavedDashboardPanel(panel, kibanaVersion) + ) + : undefined; + return { ...state, panels: savedDashboardPanels }; }; diff --git a/src/plugins/dashboard/public/application/lib/diff_dashboard_state.test.ts b/src/plugins/dashboard/public/application/lib/diff_dashboard_state.test.ts index beef010ddd1cf..9bcdbd1bed9aa 100644 --- a/src/plugins/dashboard/public/application/lib/diff_dashboard_state.test.ts +++ b/src/plugins/dashboard/public/application/lib/diff_dashboard_state.test.ts @@ -41,6 +41,7 @@ const getDashboardState = (state?: Partial): DashboardState => { useMargins: true, syncColors: false, syncTooltips: false, + syncCursor: true, }, panels: { panel_1: { @@ -99,6 +100,7 @@ describe('Dashboard state diff function', () => { useMargins: false, syncColors: false, syncTooltips: false, + syncCursor: true, }, }) ).toEqual(['options']); @@ -111,6 +113,7 @@ describe('Dashboard state diff function', () => { useMargins: true, syncColors: undefined, syncTooltips: undefined, + syncCursor: true, } as unknown as DashboardOptions, }) ).toEqual([]); diff --git a/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts b/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts index 669bde5c3eb65..61a9c75dac410 100644 --- a/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts +++ b/src/plugins/dashboard/public/application/state/dashboard_state_slice.ts @@ -61,6 +61,9 @@ export const dashboardStateSlice = createSlice({ setSyncColors: (state, action: PayloadAction) => { state.options.syncColors = action.payload; }, + setSyncCursor: (state, action: PayloadAction) => { + state.options.syncCursor = action.payload; + }, setSyncTooltips: (state, action: PayloadAction) => { state.options.syncTooltips = action.payload; }, @@ -128,6 +131,7 @@ export const { setTimeRange, setSyncColors, setSyncTooltips, + setSyncCursor, setUseMargins, setViewMode, setFilters, diff --git a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx index 97630c48dc784..3e9697d56d657 100644 --- a/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/application/top_nav/dashboard_top_nav.tsx @@ -39,6 +39,7 @@ import { setStateFromSaveModal, setSyncColors, setSyncTooltips, + setSyncCursor, setUseMargins, setViewMode, useDashboardDispatch, @@ -402,6 +403,10 @@ export function DashboardTopNav({ onSyncColorsChange: (isChecked: boolean) => { dispatchDashboardStateChange(setSyncColors(isChecked)); }, + syncCursor: currentState.options.syncCursor ?? true, + onSyncCursorChange: (isChecked: boolean) => { + dispatchDashboardStateChange(setSyncCursor(isChecked)); + }, syncTooltips: Boolean(currentState.options.syncTooltips), onSyncTooltipsChange: (isChecked: boolean) => { dispatchDashboardStateChange(setSyncTooltips(isChecked)); @@ -512,7 +517,6 @@ export function DashboardTopNav({ return { badges, screenTitle, - showQueryBar, showSearchBar, showFilterBar, showSaveQuery, diff --git a/src/plugins/dashboard/public/application/top_nav/options.tsx b/src/plugins/dashboard/public/application/top_nav/options.tsx index 3b20da4c7c1a3..65a41c7099af0 100644 --- a/src/plugins/dashboard/public/application/top_nav/options.tsx +++ b/src/plugins/dashboard/public/application/top_nav/options.tsx @@ -18,6 +18,8 @@ interface Props { onHidePanelTitlesChange: (hideTitles: boolean) => void; syncColors: boolean; onSyncColorsChange: (syncColors: boolean) => void; + syncCursor: boolean; + onSyncCursorChange: (syncCursor: boolean) => void; syncTooltips: boolean; onSyncTooltipsChange: (syncTooltips: boolean) => void; } @@ -26,6 +28,7 @@ interface State { useMargins: boolean; hidePanelTitles: boolean; syncColors: boolean; + syncCursor: boolean; syncTooltips: boolean; } @@ -34,6 +37,7 @@ export class OptionsMenu extends Component { useMargins: this.props.useMargins, hidePanelTitles: this.props.hidePanelTitles, syncColors: this.props.syncColors, + syncCursor: this.props.syncCursor, syncTooltips: this.props.syncTooltips, }; @@ -59,6 +63,12 @@ export class OptionsMenu extends Component { this.setState({ syncColors: isChecked }); }; + handleSyncCursorChange = (evt: any) => { + const isChecked = evt.target.checked; + this.props.onSyncCursorChange(isChecked); + this.setState({ syncCursor: isChecked }); + }; + handleSyncTooltipsChange = (evt: any) => { const isChecked = evt.target.checked; this.props.onSyncTooltipsChange(isChecked); @@ -89,27 +99,49 @@ export class OptionsMenu extends Component { data-test-subj="dashboardPanelTitlesCheckbox" /> - - - - - - - + + <> + + + + + + + + + + ); diff --git a/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx b/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx index 253c14f531fdf..0025fb00fa80f 100644 --- a/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx +++ b/src/plugins/dashboard/public/application/top_nav/show_options_popover.tsx @@ -31,6 +31,8 @@ export interface ShowOptionsPopoverProps { onUseMarginsChange: (useMargins: boolean) => void; syncColors: boolean; onSyncColorsChange: (syncColors: boolean) => void; + syncCursor: boolean; + onSyncCursorChange: (syncCursor: boolean) => void; syncTooltips: boolean; onSyncTooltipsChange: (syncTooltips: boolean) => void; hidePanelTitles: boolean; @@ -45,6 +47,8 @@ export function showOptionsPopover({ onHidePanelTitlesChange, syncColors, onSyncColorsChange, + syncCursor, + onSyncCursorChange, syncTooltips, onSyncTooltipsChange, }: ShowOptionsPopoverProps) { @@ -78,6 +82,8 @@ export function showOptionsPopover({ onHidePanelTitlesChange={onHidePanelTitlesChange} syncColors={syncColors} onSyncColorsChange={onSyncColorsChange} + syncCursor={syncCursor} + onSyncCursorChange={onSyncCursorChange} syncTooltips={syncTooltips} onSyncTooltipsChange={onSyncTooltipsChange} /> diff --git a/src/plugins/dashboard/public/application/top_nav/show_share_modal.test.tsx b/src/plugins/dashboard/public/application/top_nav/show_share_modal.test.tsx index 7e76ef1789a38..5f6dc325ce97a 100644 --- a/src/plugins/dashboard/public/application/top_nav/show_share_modal.test.tsx +++ b/src/plugins/dashboard/public/application/top_nav/show_share_modal.test.tsx @@ -109,6 +109,7 @@ describe('ShowShareModal', () => { hidePanelTitles: true, useMargins: true, syncColors: true, + syncCursor: true, syncTooltips: true, }, filters: [ diff --git a/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx b/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx index 0f7d119427dd7..6cff8ff20a9dd 100644 --- a/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx +++ b/src/plugins/dashboard/public/application/top_nav/show_share_modal.tsx @@ -8,11 +8,14 @@ import moment from 'moment'; import React, { ReactElement, useState } from 'react'; +import { omit } from 'lodash'; import { i18n } from '@kbn/i18n'; import { EuiCheckboxGroup } from '@elastic/eui'; +import { QueryState } from '@kbn/data-plugin/common'; import type { Capabilities } from '@kbn/core/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; +import { getStateFromKbnUrl } from '@kbn/kibana-utils-plugin/public'; import { setStateToKbnUrl, unhashUrl } from '@kbn/kibana-utils-plugin/public'; import type { SerializableControlGroupInput } from '@kbn/controls-plugin/common'; @@ -21,8 +24,8 @@ import { dashboardUrlParams } from '../dashboard_router'; import { shareModalStrings } from '../../dashboard_strings'; import { convertPanelMapToSavedPanels } from '../../../common'; import { pluginServices } from '../../services/plugin_services'; -import { stateToRawDashboardState } from '../lib/convert_dashboard_state'; import { DashboardAppLocatorParams, DASHBOARD_APP_LOCATOR } from '../../locator'; +import { stateToRawDashboardState } from '../lib/convert_dashboard_state'; const showFilterBarId = 'showFilterBar'; @@ -55,8 +58,8 @@ export function ShowShareModal({ }, }, }, - share: { toggleShareContextMenu }, initializerContext: { kibanaVersion }, + share: { toggleShareContextMenu }, } = pluginServices.getServices(); if (!toggleShareContextMenu) return; // TODO: Make this logic cleaner once share is an optional service @@ -151,19 +154,25 @@ export function ShowShareModal({ ...unsavedStateForLocator, }; + let _g = getStateFromKbnUrl('_g', window.location.href); + if (_g?.filters && _g.filters.length === 0) { + _g = omit(_g, 'filters'); + } + const baseUrl = setStateToKbnUrl('_g', _g); + + const shareableUrl = setStateToKbnUrl( + '_a', + stateToRawDashboardState({ state: unsavedDashboardState ?? {} }), + { useHash: false, storeInHashQuery: true }, + unhashUrl(baseUrl) + ); + toggleShareContextMenu({ isDirty, anchorElement, allowEmbed: true, allowShortUrl, - shareableUrl: setStateToKbnUrl( - '_a', - stateToRawDashboardState({ - state: currentDashboardState, - }), - { useHash: false, storeInHashQuery: true }, - unhashUrl(window.location.href) - ), + shareableUrl, objectId: savedObjectId, objectType: 'dashboard', sharingData: { @@ -185,5 +194,8 @@ export function ShowShareModal({ }, ], showPublicUrlSwitch, + snapshotShareWarning: Boolean(unsavedDashboardState?.panels) + ? shareModalStrings.getSnapshotShareWarning() + : undefined, }); } diff --git a/src/plugins/dashboard/public/dashboard_constants.ts b/src/plugins/dashboard/public/dashboard_constants.ts index 9bbe97681032d..c4856f8e2e34a 100644 --- a/src/plugins/dashboard/public/dashboard_constants.ts +++ b/src/plugins/dashboard/public/dashboard_constants.ts @@ -46,6 +46,7 @@ export const defaultDashboardState: DashboardState = { options: { useMargins: true, syncColors: false, + syncCursor: true, syncTooltips: false, hidePanelTitles: false, }, diff --git a/src/plugins/dashboard/public/dashboard_strings.ts b/src/plugins/dashboard/public/dashboard_strings.ts index 6474c7dc2bba6..fcb7f3cb2a7c1 100644 --- a/src/plugins/dashboard/public/dashboard_strings.ts +++ b/src/plugins/dashboard/public/dashboard_strings.ts @@ -278,6 +278,11 @@ export const shareModalStrings = { i18n.translate('dashboard.embedUrlParamExtension.include', { defaultMessage: 'Include', }), + getSnapshotShareWarning: () => + i18n.translate('dashboard.snapshotShare.longUrlWarning', { + defaultMessage: + 'One or more panels on this dashboard have changed. Before you generate a snapshot, save the dashboard.', + }), }; export const leaveConfirmStrings = { diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts index 6b24317338ab3..a9de47f63235b 100644 --- a/src/plugins/dashboard/public/types.ts +++ b/src/plugins/dashboard/public/types.ts @@ -71,6 +71,7 @@ export interface DashboardContainerInput extends ContainerInput { useMargins: boolean; syncColors?: boolean; syncTooltips?: boolean; + syncCursor?: boolean; viewMode: ViewMode; filters: Filter[]; title: string; @@ -118,6 +119,7 @@ export type DashboardOptions = { hidePanelTitles: boolean; useMargins: boolean; syncColors: boolean; + syncCursor: boolean; syncTooltips: boolean; }; diff --git a/src/plugins/data/public/search/fetch/handle_warnings.test.ts b/src/plugins/data/public/search/fetch/handle_warnings.test.ts index 8a1bb86b9f71c..0d644d8dc0811 100644 --- a/src/plugins/data/public/search/fetch/handle_warnings.test.ts +++ b/src/plugins/data/public/search/fetch/handle_warnings.test.ts @@ -45,13 +45,17 @@ const warnings: SearchResponseWarning[] = [ }, ]; +const sessionId = 'abcd'; + describe('Filtering and showing warnings', () => { const notifications = notificationServiceMock.createStartContract(); + jest.useFakeTimers('modern'); describe('handleWarnings', () => { const request = { body: {} }; beforeEach(() => { jest.resetAllMocks(); + jest.advanceTimersByTime(30000); setNotifications(notifications); (notifications.toasts.addWarning as jest.Mock).mockReset(); (extract.extractWarnings as jest.Mock).mockImplementation(() => warnings); @@ -60,10 +64,16 @@ describe('Filtering and showing warnings', () => { test('should notify if timed out', () => { (extract.extractWarnings as jest.Mock).mockImplementation(() => [warnings[0]]); const response = { rawResponse: { timed_out: true } } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme); + handleWarnings({ request, response, theme }); + // test debounce, addWarning should only be called once + handleWarnings({ request, response, theme }); expect(notifications.toasts.addWarning).toBeCalledTimes(1); expect(notifications.toasts.addWarning).toBeCalledWith({ title: 'Something timed out!' }); + + // test debounce, call addWarning again due to sessionId + handleWarnings({ request, response, theme, sessionId }); + expect(notifications.toasts.addWarning).toBeCalledTimes(2); }); test('should notify if shards failed for unknown type/reason', () => { @@ -71,10 +81,16 @@ describe('Filtering and showing warnings', () => { const response = { rawResponse: { _shards: { failed: 1, total: 2, successful: 1, skipped: 1 } }, } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme); + handleWarnings({ request, response, theme }); + // test debounce, addWarning should only be called once + handleWarnings({ request, response, theme }); expect(notifications.toasts.addWarning).toBeCalledTimes(1); expect(notifications.toasts.addWarning).toBeCalledWith({ title: 'Some shards failed!' }); + + // test debounce, call addWarning again due to sessionId + handleWarnings({ request, response, theme, sessionId }); + expect(notifications.toasts.addWarning).toBeCalledTimes(2); }); test('should add mount point for shard modal failure button if warning.text is provided', () => { @@ -82,13 +98,19 @@ describe('Filtering and showing warnings', () => { const response = { rawResponse: { _shards: { failed: 1, total: 2, successful: 1, skipped: 1 } }, } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme); + handleWarnings({ request, response, theme }); + // test debounce, addWarning should only be called once + handleWarnings({ request, response, theme }); expect(notifications.toasts.addWarning).toBeCalledTimes(1); expect(notifications.toasts.addWarning).toBeCalledWith({ title: 'Some shards failed!', text: expect.any(Function), }); + + // test debounce, call addWarning again due to sessionId + handleWarnings({ request, response, theme, sessionId }); + expect(notifications.toasts.addWarning).toBeCalledTimes(2); }); test('should notify once if the response contains multiple failures', () => { @@ -96,7 +118,7 @@ describe('Filtering and showing warnings', () => { const response = { rawResponse: { _shards: { failed: 1, total: 2, successful: 1, skipped: 1 } }, } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme); + handleWarnings({ request, response, theme }); expect(notifications.toasts.addWarning).toBeCalledTimes(1); expect(notifications.toasts.addWarning).toBeCalledWith({ @@ -111,7 +133,7 @@ describe('Filtering and showing warnings', () => { const response = { rawResponse: { _shards: { failed: 1, total: 2, successful: 1, skipped: 1 } }, } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme, callback); + handleWarnings({ request, response, theme, callback }); expect(notifications.toasts.addWarning).toBeCalledTimes(1); expect(notifications.toasts.addWarning).toBeCalledWith({ title: 'Some shards failed!' }); @@ -122,7 +144,7 @@ describe('Filtering and showing warnings', () => { const response = { rawResponse: { _shards: { failed: 1, total: 2, successful: 1, skipped: 1 } }, } as unknown as estypes.SearchResponse; - handleWarnings(request, response, theme, callback); + handleWarnings({ request, response, theme, callback }); expect(notifications.toasts.addWarning).toBeCalledTimes(0); }); diff --git a/src/plugins/data/public/search/fetch/handle_warnings.tsx b/src/plugins/data/public/search/fetch/handle_warnings.tsx index 0ffb6389f81c4..1720ea1f76c0c 100644 --- a/src/plugins/data/public/search/fetch/handle_warnings.tsx +++ b/src/plugins/data/public/search/fetch/handle_warnings.tsx @@ -7,10 +7,12 @@ */ import { estypes } from '@elastic/elasticsearch'; +import { debounce } from 'lodash'; import { EuiSpacer } from '@elastic/eui'; import { ThemeServiceStart } from '@kbn/core/public'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import React from 'react'; +import type { MountPoint } from '@kbn/core/public'; import { SearchRequest } from '..'; import { getNotifications } from '../../services'; import { ShardFailureOpenModalButton, ShardFailureRequest } from '../../shard_failure_modal'; @@ -21,23 +23,53 @@ import { } from '../types'; import { extractWarnings } from './extract_warnings'; +const getDebouncedWarning = () => { + const addWarning = () => { + const { toasts } = getNotifications(); + return debounce(toasts.addWarning.bind(toasts), 30000, { + leading: true, + }); + }; + const memory: Record> = {}; + + return ( + debounceKey: string, + title: string, + text?: string | MountPoint | undefined + ) => { + memory[debounceKey] = memory[debounceKey] || addWarning(); + return memory[debounceKey]({ title, text }); + }; +}; + +const debouncedWarningWithoutReason = getDebouncedWarning(); +const debouncedTimeoutWarning = getDebouncedWarning(); +const debouncedWarning = getDebouncedWarning(); + /** * @internal * All warnings are expected to come from the same response. Therefore all "text" properties, which contain the * response, will be the same. */ -export function handleWarnings( - request: SearchRequest, - response: estypes.SearchResponse, - theme: ThemeServiceStart, - cb?: WarningHandlerCallback -) { +export function handleWarnings({ + request, + response, + theme, + callback, + sessionId = '', +}: { + request: SearchRequest; + response: estypes.SearchResponse; + theme: ThemeServiceStart; + callback?: WarningHandlerCallback; + sessionId?: string; +}) { const warnings = extractWarnings(response); if (warnings.length === 0) { return; } - const internal = cb ? filterWarnings(warnings, cb) : warnings; + const internal = callback ? filterWarnings(warnings, callback) : warnings; if (internal.length === 0) { return; } @@ -45,9 +77,7 @@ export function handleWarnings( // timeout notification const [timeout] = internal.filter((w) => w.type === 'timed_out'); if (timeout) { - getNotifications().toasts.addWarning({ - title: timeout.message, - }); + debouncedTimeoutWarning(sessionId + timeout.message, timeout.message); } // shard warning failure notification @@ -75,12 +105,12 @@ export function handleWarnings( { theme$: theme.theme$ } ); - getNotifications().toasts.addWarning({ title, text }); + debouncedWarning(sessionId + warning.text, title, text); return; } // timeout warning, or shard warning with no failure reason - getNotifications().toasts.addWarning({ title }); + debouncedWarningWithoutReason(sessionId + title, title); } /** diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 432549698eed2..c1c8fc37a0e72 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -27,6 +27,7 @@ describe('Search service', () => { let mockCoreSetup: MockedKeys; let mockCoreStart: MockedKeys; const initializerContext = coreMock.createPluginInitializerContext(); + jest.useFakeTimers('modern'); initializerContext.config.get = jest.fn().mockReturnValue({ search: { aggs: { shardDelay: { enabled: false } }, sessions: { enabled: true } }, }); @@ -35,6 +36,7 @@ describe('Search service', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); searchService = new SearchService(initializerContext); + jest.advanceTimersByTime(30000); }); describe('setup()', () => { @@ -217,7 +219,13 @@ describe('Search service', () => { const responder1 = inspector.adapter.start('request1'); const responder2 = inspector.adapter.start('request2'); responder1.ok(getMockResponseWithShards(shards)); - responder2.ok(getMockResponseWithShards(shards)); + responder2.ok({ + json: { + rawResponse: { + timed_out: true, + }, + }, + }); data.showWarnings(inspector.adapter, callback); @@ -227,8 +235,7 @@ describe('Search service', () => { text: expect.any(Function), }); expect(notifications.toasts.addWarning).nthCalledWith(2, { - title: '2 of 4 shards failed', - text: expect.any(Function), + title: 'Data might be incomplete because your request timed out', }); }); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index c88201405d7f0..e7b753838edff 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -240,7 +240,12 @@ export class SearchService implements Plugin { onResponse: (request, response, options) => { if (!options.disableShardFailureWarning) { const { rawResponse } = response; - handleWarnings(request.body, rawResponse, theme); + handleWarnings({ + request: request.body, + response: rawResponse, + theme, + sessionId: options.sessionId, + }); } return response; }, @@ -271,7 +276,7 @@ export class SearchService implements Plugin { showError: (e) => { this.searchInterceptor.showError(e); }, - showWarnings: (adapter, cb) => { + showWarnings: (adapter, callback) => { adapter?.getRequests().forEach((request) => { const rawResponse = ( request.response?.json as { rawResponse: estypes.SearchResponse | undefined } @@ -281,7 +286,12 @@ export class SearchService implements Plugin { return; } - handleWarnings(request.json as SearchRequest, rawResponse, theme, cb); + handleWarnings({ + request: request.json as SearchRequest, + response: rawResponse, + theme, + callback, + }); }); }, session: this.sessionService, diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index 98f5f906113b6..9c86170795961 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useEffect, useCallback, useRef, useContext } from 'react'; import { EuiTitle, EuiFlexGroup, @@ -15,14 +15,12 @@ import { EuiLoadingSpinner, EuiLink, } from '@elastic/eui'; + import { i18n } from '@kbn/i18n'; import memoizeOne from 'memoize-one'; -import { - DataViewField, - DataViewsPublicPluginStart, - INDEX_PATTERN_TYPE, - MatchedItem, -} from '@kbn/data-views-plugin/public'; +import { BehaviorSubject } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; +import { INDEX_PATTERN_TYPE, MatchedItem } from '@kbn/data-views-plugin/public'; import { DataView, @@ -31,11 +29,10 @@ import { useForm, useFormData, useKibana, - GetFieldsOptions, UseField, } from '../shared_imports'; -import { ensureMinimumTime, extractTimeFields, getMatchedIndices } from '../lib'; +import { ensureMinimumTime, getMatchedIndices } from '../lib'; import { FlyoutPanels } from './flyout_panels'; import { removeSpaces } from '../lib'; @@ -46,7 +43,6 @@ import { IndexPatternConfig, MatchedIndicesSet, FormInternal, - TimestampOption, } from '../types'; import { @@ -61,6 +57,8 @@ import { RollupBetaWarning, } from '.'; import { editDataViewModal } from './confirm_modals/edit_data_view_changed_modal'; +import { DataViewEditorServiceContext } from './data_view_flyout_content_container'; +import { DataViewEditorService } from '../data_view_editor_service'; export interface Props { /** @@ -78,6 +76,13 @@ export interface Props { allowAdHoc: boolean; } +export const matchedIndiciesDefault = { + allIndices: [], + exactMatchedIndices: [], + partialMatchedIndices: [], + visibleIndices: [], +}; + const editorTitle = i18n.translate('indexPatternEditor.title', { defaultMessage: 'Create data view', }); @@ -96,9 +101,11 @@ const IndexPatternEditorFlyoutContentComponent = ({ showManagementLink, }: Props) => { const { - services: { application, http, dataViews, uiSettings, overlays }, + services: { application, dataViews, uiSettings, overlays }, } = useKibana(); + const { dataViewEditorService } = useContext(DataViewEditorServiceContext); + const canSave = dataViews.getCanSaveSync(); const { form } = useForm({ @@ -125,12 +132,15 @@ const IndexPatternEditorFlyoutContentComponent = ({ return; } + const rollupIndicesCapabilities = dataViewEditorService.rollupIndicesCapabilities$.getValue(); + const indexPatternStub: DataViewSpec = { title: removeSpaces(formData.title), timeFieldName: formData.timestampField?.value, id: formData.id, name: formData.name, }; + const rollupIndex = rollupIndex$.current.getValue(); if (type === INDEX_PATTERN_TYPE.ROLLUP && rollupIndex) { indexPatternStub.type = INDEX_PATTERN_TYPE.ROLLUP; @@ -156,8 +166,6 @@ const IndexPatternEditorFlyoutContentComponent = ({ }, }); - const { getFields } = form; - // `useFormData` initially returns `undefined`, // we override `undefined` with real default values from `schema` // to get a stable reference to avoid hooks re-run and reduce number of excessive requests @@ -168,148 +176,92 @@ const IndexPatternEditorFlyoutContentComponent = ({ type = schema.type.defaultValue, }, ] = useFormData({ form }); - const [isLoadingSources, setIsLoadingSources] = useState(true); - const [timestampFieldOptions, setTimestampFieldOptions] = useState([]); - const [isLoadingTimestampFields, setIsLoadingTimestampFields] = useState(false); - const currentLoadingTimestampFieldsRef = useRef(0); - const [isLoadingMatchedIndices, setIsLoadingMatchedIndices] = useState(false); const currentLoadingMatchedIndicesRef = useRef(0); - const [allSources, setAllSources] = useState([]); - const [isLoadingIndexPatterns, setIsLoadingIndexPatterns] = useState(true); - const [existingIndexPatterns, setExistingIndexPatterns] = useState([]); - const [rollupIndex, setRollupIndex] = useState(); - const [rollupIndicesCapabilities, setRollupIndicesCapabilities] = - useState({}); - const [matchedIndices, setMatchedIndices] = useState({ - allIndices: [], - exactMatchedIndices: [], - partialMatchedIndices: [], - visibleIndices: [], - }); - // load all data sources and set initial matchedIndices - const loadSources = useCallback(() => { - dataViews - .getIndices({ - isRollupIndex: () => false, - pattern: '*', - showAllIndices: allowHidden, - }) - .then((dataSources) => { - setAllSources(dataSources); - const matchedSet = getMatchedIndices(dataSources, [], [], allowHidden); - setMatchedIndices(matchedSet); - setIsLoadingSources(false); - }); - }, [allowHidden, dataViews]); + const isLoadingSources = useObservable(dataViewEditorService.isLoadingSources$, true); - // loading list of index patterns - useEffect(() => { - loadSources(); - const getTitles = async () => { - const dataViewListItems = await dataViews.getIdsWithTitle(editData ? true : false); - const indexPatternNames = dataViewListItems.map((item) => item.name || item.title); + const loadingMatchedIndices$ = useRef(new BehaviorSubject(false)); - setExistingIndexPatterns( - editData ? indexPatternNames.filter((v) => v !== editData.name) : indexPatternNames - ); - setIsLoadingIndexPatterns(false); - }; - getTitles(); - }, [http, dataViews, editData, loadSources]); + const isLoadingDataViewNames$ = useRef(new BehaviorSubject(true)); + const existingDataViewNames$ = useRef(new BehaviorSubject([])); + const isLoadingDataViewNames = useObservable(isLoadingDataViewNames$.current, true); + + const rollupIndicesCapabilities = useObservable( + dataViewEditorService.rollupIndicesCapabilities$, + {} + ); + + const rollupIndex$ = useRef(new BehaviorSubject(undefined)); - // loading rollup info + // initial loading of indicies and data view names useEffect(() => { - const getRollups = async () => { - try { - const response = await http.get('/api/rollup/indices'); - if (response) { - setRollupIndicesCapabilities(response); - } - } catch (e) { - // Silently swallow failure responses such as expired trials - } + let isCancelled = false; + const matchedIndicesSub = dataViewEditorService.matchedIndices$.subscribe((matchedIndices) => { + const timeFieldQuery = editData ? editData.title : title; + dataViewEditorService.loadTimestampFields( + removeSpaces(timeFieldQuery), + type, + requireTimestampField, + rollupIndex$.current.getValue() + ); + }); + + dataViewEditorService.loadIndices(title, allowHidden).then((matchedIndices) => { + if (isCancelled) return; + dataViewEditorService.matchedIndices$.next(matchedIndices); + }); + + dataViewEditorService.loadDataViewNames(title).then((names) => { + if (isCancelled) return; + const filteredNames = editData ? names.filter((name) => name !== editData?.name) : names; + existingDataViewNames$.current.next(filteredNames); + isLoadingDataViewNames$.current.next(false); + }); + + return () => { + isCancelled = true; + matchedIndicesSub.unsubscribe(); }; - - getRollups(); - }, [http, type]); + }, [editData, type, title, allowHidden, requireTimestampField, dataViewEditorService]); const getRollupIndices = (rollupCaps: RollupIndicesCapsResponse) => Object.keys(rollupCaps); - const loadTimestampFieldOptions = useCallback( - async (query: string) => { - const currentLoadingTimestampFieldsIdx = ++currentLoadingTimestampFieldsRef.current; - let timestampOptions: TimestampOption[] = []; - const isValidResult = - matchedIndices.exactMatchedIndices.length > 0 && !isLoadingMatchedIndices; - if (isValidResult) { - setIsLoadingTimestampFields(true); - const getFieldsOptions: GetFieldsOptions = { - pattern: query, - }; - if (type === INDEX_PATTERN_TYPE.ROLLUP) { - getFieldsOptions.type = INDEX_PATTERN_TYPE.ROLLUP; - getFieldsOptions.rollupIndex = rollupIndex; - } - - const fields = await ensureMinimumTime(dataViews.getFieldsForWildcard(getFieldsOptions)); - timestampOptions = extractTimeFields(fields as DataViewField[], requireTimestampField); - } - if (currentLoadingTimestampFieldsIdx === currentLoadingTimestampFieldsRef.current) { - setIsLoadingTimestampFields(false); - setTimestampFieldOptions(timestampOptions); - } - return timestampOptions; - }, - [ - dataViews, - requireTimestampField, - rollupIndex, - type, - matchedIndices.exactMatchedIndices, - isLoadingMatchedIndices, - ] - ); - + // used in title field validation const reloadMatchedIndices = useCallback( async (newTitle: string) => { - const isRollupIndex = (indexName: string) => - getRollupIndices(rollupIndicesCapabilities).includes(indexName); let newRollupIndexName: string | undefined; const fetchIndices = async (query: string = '') => { const currentLoadingMatchedIndicesIdx = ++currentLoadingMatchedIndicesRef.current; - setIsLoadingMatchedIndices(true); + loadingMatchedIndices$.current.next(true); + + const allSrcs = await dataViewEditorService.getIndicesCached({ + pattern: '*', + showAllIndices: allowHidden, + }); const { matchedIndicesResult, exactMatched } = !isLoadingSources - ? await loadMatchedIndices(query, allowHidden, allSources, { - isRollupIndex, - dataViews, - }) + ? await loadMatchedIndices(query, allowHidden, allSrcs, dataViewEditorService) : { - matchedIndicesResult: { - exactMatchedIndices: [], - allIndices: [], - partialMatchedIndices: [], - visibleIndices: [], - }, + matchedIndicesResult: matchedIndiciesDefault, exactMatched: [], }; if (currentLoadingMatchedIndicesIdx === currentLoadingMatchedIndicesRef.current) { // we are still interested in this result if (type === INDEX_PATTERN_TYPE.ROLLUP) { + const isRollupIndex = await dataViewEditorService.getIsRollupIndex(); const rollupIndices = exactMatched.filter((index) => isRollupIndex(index.name)); newRollupIndexName = rollupIndices.length === 1 ? rollupIndices[0].name : undefined; - setRollupIndex(newRollupIndexName); + rollupIndex$.current.next(newRollupIndexName); } else { - setRollupIndex(undefined); + rollupIndex$.current.next(undefined); } - setMatchedIndices(matchedIndicesResult); - setIsLoadingMatchedIndices(false); + dataViewEditorService.matchedIndices$.next(matchedIndicesResult); + loadingMatchedIndices$.current.next(false); } return { matchedIndicesResult, newRollupIndexName }; @@ -317,27 +269,16 @@ const IndexPatternEditorFlyoutContentComponent = ({ return fetchIndices(newTitle); }, - [dataViews, allowHidden, allSources, type, rollupIndicesCapabilities, isLoadingSources] + [ + allowHidden, + type, + dataViewEditorService, + rollupIndex$, + isLoadingSources, + loadingMatchedIndices$, + ] ); - // If editData exists, loadSources so that MatchedIndices can be loaded for the Timestampfields - useEffect(() => { - if (editData) { - loadSources(); - reloadMatchedIndices(removeSpaces(editData.getIndexPattern())); - } - // We use the below eslint-disable as adding 'loadSources' and 'reloadMatchedIndices' as a dependency creates an infinite loop - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [editData]); - - useEffect(() => { - const timeFieldQuery = editData ? editData.title : title; - loadTimestampFieldOptions(removeSpaces(timeFieldQuery)); - if (!editData) getFields().timestampField?.setValue(''); - // We use the below eslint-disable as adding editData as a dependency create an infinite loop - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [loadTimestampFieldOptions, title, getFields]); - const onTypeChange = useCallback( (newType) => { form.setFieldValue('title', ''); @@ -350,7 +291,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ [form] ); - if (isLoadingSources || isLoadingIndexPatterns) { + if (isLoadingSources || isLoadingDataViewNames) { return ; } @@ -404,7 +345,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ - + @@ -413,7 +354,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ @@ -422,10 +363,10 @@ const IndexPatternEditorFlyoutContentComponent = ({ @@ -460,7 +401,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ type={type} allowHidden={allowHidden} title={title} - matched={matchedIndices} + matchedIndices$={dataViewEditorService.matchedIndices$} /> )} @@ -479,13 +420,7 @@ const loadMatchedIndices = memoizeOne( query: string, allowHidden: boolean, allSources: MatchedItem[], - { - isRollupIndex, - dataViews, - }: { - isRollupIndex: (index: string) => boolean; - dataViews: DataViewsPublicPluginStart; - } + dataViewEditorService: DataViewEditorService ): Promise<{ matchedIndicesResult: MatchedIndicesSet; exactMatched: MatchedItem[]; @@ -494,8 +429,7 @@ const loadMatchedIndices = memoizeOne( const indexRequests = []; if (query?.endsWith('*')) { - const exactMatchedQuery = dataViews.getIndices({ - isRollupIndex, + const exactMatchedQuery = dataViewEditorService.getIndicesCached({ pattern: query, showAllIndices: allowHidden, }); @@ -503,13 +437,11 @@ const loadMatchedIndices = memoizeOne( // provide default value when not making a request for the partialMatchQuery indexRequests.push(Promise.resolve([])); } else { - const exactMatchQuery = dataViews.getIndices({ - isRollupIndex, + const exactMatchQuery = dataViewEditorService.getIndicesCached({ pattern: query, showAllIndices: allowHidden, }); - const partialMatchQuery = dataViews.getIndices({ - isRollupIndex, + const partialMatchQuery = dataViewEditorService.getIndicesCached({ pattern: `${query}*`, showAllIndices: allowHidden, }); diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_lazy.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_lazy.tsx index 0abf5e3821f8e..ae3c98d512213 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_lazy.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_lazy.tsx @@ -11,12 +11,10 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { DataViewEditorProps } from '../types'; -const IndexPatternFlyoutContentContainer = lazy( - () => import('./data_view_flyout_content_container') -); +const DataViewFlyoutContentContainer = lazy(() => import('./data_view_flyout_content_container')); export const DataViewEditorLazy = (props: DataViewEditorProps) => ( }> - + ); diff --git a/src/plugins/data_view_editor/public/components/data_view_flyout_content_container.tsx b/src/plugins/data_view_editor/public/components/data_view_flyout_content_container.tsx index 3aaf56e6daaad..16e58d52624c3 100644 --- a/src/plugins/data_view_editor/public/components/data_view_flyout_content_container.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_flyout_content_container.tsx @@ -12,8 +12,14 @@ import { i18n } from '@kbn/i18n'; import { DataViewSpec, useKibana } from '../shared_imports'; import { IndexPatternEditorFlyoutContent } from './data_view_editor_flyout_content'; import { DataViewEditorContext, DataViewEditorProps } from '../types'; +import { DataViewEditorService } from '../data_view_editor_service'; -const IndexPatternFlyoutContentContainer = ({ +// @ts-ignore +export const DataViewEditorServiceContext = React.createContext<{ + dataViewEditorService: DataViewEditorService; +}>(); + +const DataViewFlyoutContentContainer = ({ onSave, onCancel = () => {}, defaultTypeIsRollup, @@ -23,7 +29,7 @@ const IndexPatternFlyoutContentContainer = ({ showManagementLink, }: DataViewEditorProps) => { const { - services: { dataViews, notifications }, + services: { dataViews, notifications, http }, } = useKibana(); const onSaveClick = async (dataViewSpec: DataViewSpec, persist: boolean = true) => { @@ -63,17 +69,21 @@ const IndexPatternFlyoutContentContainer = ({ }; return ( - + + + ); }; /* eslint-disable import/no-default-export */ -export default IndexPatternFlyoutContentContainer; +export default DataViewFlyoutContentContainer; diff --git a/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx index f2236abad5ec7..425178d452c5a 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx @@ -9,8 +9,9 @@ import React, { ChangeEvent, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { BehaviorSubject } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; import { - DataView, UseField, ValidationConfig, FieldConfig, @@ -20,8 +21,7 @@ import { IndexPatternConfig } from '../../types'; import { schema } from '../form_schema'; interface NameFieldProps { - editData?: DataView; - existingDataViewNames: string[]; + existingDataViewNames$: BehaviorSubject; } interface GetNameConfigArgs { @@ -53,13 +53,14 @@ const getNameConfig = ({ namesNotAllowed }: GetNameConfigArgs): FieldConfig { +export const NameField = ({ existingDataViewNames$ }: NameFieldProps) => { + const namesNotAllowed = useObservable(existingDataViewNames$, []); const config = useMemo( () => getNameConfig({ - namesNotAllowed: existingDataViewNames, + namesNotAllowed, }), - [existingDataViewNames] + [namesNotAllowed] ); return ( diff --git a/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx index ce36d1e1fdc99..846a9db09ee80 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx @@ -8,8 +8,10 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; - +import useObservable from 'react-use/lib/useObservable'; +import { BehaviorSubject, Subject } from 'rxjs'; import { EuiFormRow, EuiComboBox, EuiFormHelpText, EuiComboBoxOptionOption } from '@elastic/eui'; +import { matchedIndiciesDefault } from '../data_view_editor_flyout_content'; import { UseField, @@ -18,17 +20,17 @@ import { getFieldValidityAndErrorMessage, } from '../../shared_imports'; -import { TimestampOption } from '../../types'; +import { TimestampOption, MatchedIndicesSet } from '../../types'; import { schema } from '../form_schema'; interface Props { - options: TimestampOption[]; - isLoadingOptions: boolean; - isLoadingMatchedIndices: boolean; - hasMatchedIndices: boolean; + options$: Subject; + isLoadingOptions$: BehaviorSubject; + isLoadingMatchedIndices$: BehaviorSubject; + matchedIndices$: Subject; } -const requireTimestampOptionValidator = (options: Props['options']): ValidationConfig => ({ +const requireTimestampOptionValidator = (options: TimestampOption[]): ValidationConfig => ({ validator: async ({ value }) => { const isValueRequired = !!options.length; if (isValueRequired && !value) { @@ -45,7 +47,7 @@ const requireTimestampOptionValidator = (options: Props['options']): ValidationC }); const getTimestampConfig = ( - options: Props['options'] + options: TimestampOption[] ): FieldConfig> => { const timestampFieldConfig = schema.timestampField; @@ -70,15 +72,22 @@ const timestampFieldHelp = i18n.translate('indexPatternEditor.editor.form.timeFi }); export const TimestampField = ({ - options = [], - isLoadingOptions = false, - isLoadingMatchedIndices, - hasMatchedIndices, + options$, + isLoadingOptions$, + isLoadingMatchedIndices$, + matchedIndices$, }: Props) => { + const options = useObservable(options$, []); + const isLoadingOptions = useObservable(isLoadingOptions$, false); + const isLoadingMatchedIndices = useObservable(isLoadingMatchedIndices$, false); + const hasMatchedIndices = !!useObservable(matchedIndices$, matchedIndiciesDefault) + .exactMatchedIndices.length; + const optionsAsComboBoxOptions = options.map(({ display, fieldName }) => ({ label: display, value: fieldName, })); + const timestampConfig = useMemo(() => getTimestampConfig(options), [options]); const selectTimestampHelp = options.length ? timestampFieldHelp : ''; @@ -98,8 +107,12 @@ export const TimestampField = ({ const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); const isDisabled = !optionsAsComboBoxOptions.length; + // if the value isn't in the list then don't use it. + const valueInList = !!optionsAsComboBoxOptions.find( + (option) => option.value === value.value + ); - if (!value && !isDisabled) { + if ((!value || !valueInList) && !isDisabled) { const val = optionsAsComboBoxOptions.filter((el) => el.value === '@timestamp'); if (val.length) { setValue(val[0]); @@ -124,7 +137,7 @@ export const TimestampField = ({ )} singleSelection={{ asPlainText: true }} options={optionsAsComboBoxOptions} - selectedOptions={value ? [value] : undefined} + selectedOptions={value && valueInList ? [value] : undefined} onChange={(newValue) => { if (newValue.length === 0) { // Don't allow clearing the type. One must always be selected diff --git a/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx index 9a4c209a56ebf..6f443871dd66e 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx @@ -9,6 +9,8 @@ import React, { ChangeEvent, useState, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiFieldText } from '@elastic/eui'; +import { Subject } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; import { MatchedItem } from '@kbn/data-views-plugin/public'; import { UseField, @@ -19,6 +21,7 @@ import { import { canAppendWildcard, removeSpaces } from '../../lib'; import { schema } from '../form_schema'; import { RollupIndicesCapsResponse, IndexPatternConfig, MatchedIndicesSet } from '../../types'; +import { matchedIndiciesDefault } from '../data_view_editor_flyout_content'; interface RefreshMatchedIndicesResult { matchedIndicesResult: MatchedIndicesSet; @@ -27,7 +30,7 @@ interface RefreshMatchedIndicesResult { interface TitleFieldProps { isRollup: boolean; - matchedIndices: MatchedItem[]; + matchedIndices$: Subject; rollupIndicesCapabilities: RollupIndicesCapsResponse; refreshMatchedIndices: (title: string) => Promise; } @@ -134,11 +137,12 @@ const getTitleConfig = ({ export const TitleField = ({ isRollup, - matchedIndices, + matchedIndices$, rollupIndicesCapabilities, refreshMatchedIndices, }: TitleFieldProps) => { const [appendedWildcard, setAppendedWildcard] = useState(false); + const matchedIndices = useObservable(matchedIndices$, matchedIndiciesDefault).exactMatchedIndices; const fieldConfig = useMemo( () => diff --git a/src/plugins/data_view_editor/public/components/preview_panel/indices_list/indices_list.tsx b/src/plugins/data_view_editor/public/components/preview_panel/indices_list/indices_list.tsx index 51405efc58790..f307bbfc43889 100644 --- a/src/plugins/data_view_editor/public/components/preview_panel/indices_list/indices_list.tsx +++ b/src/plugins/data_view_editor/public/components/preview_panel/indices_list/indices_list.tsx @@ -144,18 +144,35 @@ export class IndicesList extends React.Component q.trim()); + let queryIdx = -1; + let queryWithoutWildcard = ''; + for (let i = 0; i < queryAsArray.length; i++) { + const queryComponent = queryAsArray[i]; + queryWithoutWildcard = queryComponent.endsWith('*') + ? queryComponent.substring(0, queryComponent.length - 1) + : queryComponent; + queryIdx = indexName.indexOf(queryWithoutWildcard); + + if (queryIdx !== -1) { + break; + } + } + if (queryIdx === -1) { + return indexName; + } + + const preStr = indexName.substring(0, queryIdx); + const postStr = indexName.substr(queryIdx + queryWithoutWildcard.length); return ( {preStr} - {query} + {queryWithoutWildcard} {postStr} ); @@ -164,15 +181,11 @@ export class IndicesList extends React.Component { return ( - - {this.highlightIndexName(index.name, queryWithoutWildcard)} - + {this.highlightIndexName(index.name, query)} {index.tags.map((tag: Tag) => { return ( diff --git a/src/plugins/data_view_editor/public/components/preview_panel/preview_panel.tsx b/src/plugins/data_view_editor/public/components/preview_panel/preview_panel.tsx index 26f6b2b1c2a70..28163384ca0f8 100644 --- a/src/plugins/data_view_editor/public/components/preview_panel/preview_panel.tsx +++ b/src/plugins/data_view_editor/public/components/preview_panel/preview_panel.tsx @@ -8,9 +8,12 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; +import useObservable from 'react-use/lib/useObservable'; +import { Subject } from 'rxjs'; import { INDEX_PATTERN_TYPE } from '@kbn/data-views-plugin/public'; import { StatusMessage } from './status_message'; import { IndicesList } from './indices_list'; +import { matchedIndiciesDefault } from '../data_view_editor_flyout_content'; import { MatchedIndicesSet } from '../../types'; @@ -18,10 +21,11 @@ interface Props { type: INDEX_PATTERN_TYPE; allowHidden: boolean; title: string; - matched: MatchedIndicesSet; + matchedIndices$: Subject; } -export const PreviewPanel = ({ type, allowHidden, title = '', matched }: Props) => { +export const PreviewPanel = ({ type, allowHidden, title = '', matchedIndices$ }: Props) => { + const matched = useObservable(matchedIndices$, matchedIndiciesDefault); const indicesListContent = matched.visibleIndices.length || matched.allIndices.length ? ( <> diff --git a/src/plugins/data_view_editor/public/data_view_editor_service.ts b/src/plugins/data_view_editor/public/data_view_editor_service.ts new file mode 100644 index 0000000000000..57963830149db --- /dev/null +++ b/src/plugins/data_view_editor/public/data_view_editor_service.ts @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { HttpSetup } from '@kbn/core/public'; +import { BehaviorSubject, Subject } from 'rxjs'; + +import { + DataViewsServicePublic, + MatchedItem, + INDEX_PATTERN_TYPE, + DataViewField, +} from '@kbn/data-views-plugin/public'; + +import { RollupIndicesCapsResponse, MatchedIndicesSet, TimestampOption } from './types'; +import { getMatchedIndices, ensureMinimumTime, extractTimeFields } from './lib'; +import { GetFieldsOptions } from './shared_imports'; + +export class DataViewEditorService { + constructor(private http: HttpSetup, private dataViews: DataViewsServicePublic) { + this.rollupCapsResponse = this.getRollupIndexCaps(); + } + + rollupIndicesCapabilities$ = new BehaviorSubject({}); + isLoadingSources$ = new BehaviorSubject(false); + + loadingTimestampFields$ = new BehaviorSubject(false); + timestampFieldOptions$ = new Subject(); + + matchedIndices$ = new BehaviorSubject({ + allIndices: [], + exactMatchedIndices: [], + partialMatchedIndices: [], + visibleIndices: [], + }); + + private rollupCapsResponse: Promise; + + private currentLoadingTimestampFields = 0; + + private getRollupIndexCaps = async () => { + let response: RollupIndicesCapsResponse = {}; + try { + response = await this.http.get('/api/rollup/indices'); + } catch (e) { + // Silently swallow failure responses such as expired trials + } + this.rollupIndicesCapabilities$.next(response); + return response; + }; + + private getRollupIndices = (rollupCaps: RollupIndicesCapsResponse) => Object.keys(rollupCaps); + + getIsRollupIndex = async () => { + const response = await this.rollupCapsResponse; + return (indexName: string) => this.getRollupIndices(response).includes(indexName); + }; + + loadMatchedIndices = async ( + query: string, + allowHidden: boolean, + allSources: MatchedItem[] + ): Promise<{ + matchedIndicesResult: MatchedIndicesSet; + exactMatched: MatchedItem[]; + partialMatched: MatchedItem[]; + }> => { + const indexRequests = []; + + if (query?.endsWith('*')) { + const exactMatchedQuery = this.getIndicesCached({ + pattern: query, + showAllIndices: allowHidden, + }); + indexRequests.push(exactMatchedQuery); + // provide default value when not making a request for the partialMatchQuery + indexRequests.push(Promise.resolve([])); + } else { + const exactMatchQuery = this.getIndicesCached({ + pattern: query, + showAllIndices: allowHidden, + }); + const partialMatchQuery = this.getIndicesCached({ + pattern: `${query}*`, + showAllIndices: allowHidden, + }); + + indexRequests.push(exactMatchQuery); + indexRequests.push(partialMatchQuery); + } + + const [exactMatched, partialMatched] = (await ensureMinimumTime( + indexRequests + )) as MatchedItem[][]; + + const matchedIndicesResult = getMatchedIndices( + allSources, + partialMatched, + exactMatched, + allowHidden + ); + + this.matchedIndices$.next(matchedIndicesResult); + return { matchedIndicesResult, exactMatched, partialMatched }; + }; + + loadIndices = async (title: string, allowHidden: boolean) => { + const allSrcs = await this.getIndicesCached({ + pattern: '*', + showAllIndices: allowHidden, + }); + + const matchedSet = await this.loadMatchedIndices(title, allowHidden, allSrcs); + + this.isLoadingSources$.next(false); + const matchedIndices = getMatchedIndices( + allSrcs, + matchedSet.partialMatched, + matchedSet.exactMatched, + allowHidden + ); + + this.matchedIndices$.next(matchedIndices); + return matchedIndices; + }; + + loadDataViewNames = async (dataViewName?: string) => { + const dataViewListItems = await this.dataViews.getIdsWithTitle(dataViewName ? true : false); + const dataViewNames = dataViewListItems.map((item) => item.name || item.title); + return dataViewName ? dataViewNames.filter((v) => v !== dataViewName) : dataViewNames; + }; + + private getIndicesMemory: Record> = {}; + getIndicesCached = async (props: { pattern: string; showAllIndices?: boolean | undefined }) => { + const key = JSON.stringify(props); + + const getIndicesPromise = this.getIsRollupIndex().then((isRollupIndex) => + this.dataViews.getIndices({ ...props, isRollupIndex }) + ); + this.getIndicesMemory[key] = this.getIndicesMemory[key] || getIndicesPromise; + + getIndicesPromise.catch(() => { + delete this.getIndicesMemory[key]; + }); + + return await getIndicesPromise; + }; + + private timeStampOptionsMemory: Record> = {}; + private getTimestampOptionsForWildcard = async ( + getFieldsOptions: GetFieldsOptions, + requireTimestampField: boolean + ) => { + const fields = await ensureMinimumTime(this.dataViews.getFieldsForWildcard(getFieldsOptions)); + return extractTimeFields(fields as DataViewField[], requireTimestampField); + }; + + private getTimestampOptionsForWildcardCached = async ( + getFieldsOptions: GetFieldsOptions, + requireTimestampField: boolean + ) => { + const key = JSON.stringify(getFieldsOptions) + requireTimestampField; + + const getTimestampOptionsPromise = this.getTimestampOptionsForWildcard( + getFieldsOptions, + requireTimestampField + ); + this.timeStampOptionsMemory[key] = + this.timeStampOptionsMemory[key] || getTimestampOptionsPromise; + + getTimestampOptionsPromise.catch(() => { + delete this.timeStampOptionsMemory[key]; + }); + + return await getTimestampOptionsPromise; + }; + + loadTimestampFields = async ( + index: string, + type: INDEX_PATTERN_TYPE, + requireTimestampField: boolean, + rollupIndex?: string + ) => { + if (this.matchedIndices$.getValue().exactMatchedIndices.length === 0) { + this.timestampFieldOptions$.next([]); + return; + } + const currentLoadingTimestampFieldsIdx = ++this.currentLoadingTimestampFields; + this.loadingTimestampFields$.next(true); + const getFieldsOptions: GetFieldsOptions = { + pattern: index, + }; + if (type === INDEX_PATTERN_TYPE.ROLLUP) { + getFieldsOptions.type = INDEX_PATTERN_TYPE.ROLLUP; + getFieldsOptions.rollupIndex = rollupIndex; + } + + let timestampOptions: TimestampOption[] = []; + try { + timestampOptions = await this.getTimestampOptionsForWildcardCached( + getFieldsOptions, + requireTimestampField + ); + } finally { + if (currentLoadingTimestampFieldsIdx === this.currentLoadingTimestampFields) { + this.timestampFieldOptions$.next(timestampOptions); + this.loadingTimestampFields$.next(false); + } + } + }; +} diff --git a/src/plugins/data_view_editor/public/open_editor.tsx b/src/plugins/data_view_editor/public/open_editor.tsx index 29ea140daef4b..3f998601f38f1 100644 --- a/src/plugins/data_view_editor/public/open_editor.tsx +++ b/src/plugins/data_view_editor/public/open_editor.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { CoreStart, OverlayRef } from '@kbn/core/public'; import { I18nProvider } from '@kbn/i18n-react'; -import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import { createKibanaReactContext, toMountPoint, DataPublicPluginStart } from './shared_imports'; @@ -20,7 +20,7 @@ import { DataViewEditorLazy } from './components/data_view_editor_lazy'; interface Dependencies { core: CoreStart; searchClient: DataPublicPluginStart['search']['search']; - dataViews: DataViewsPublicPluginStart; + dataViews: DataViewsServicePublic; } export const getEditorOpener = diff --git a/src/plugins/data_view_editor/public/plugin.test.tsx b/src/plugins/data_view_editor/public/plugin.test.tsx index 37e8002067613..a95da2edc44f8 100644 --- a/src/plugins/data_view_editor/public/plugin.test.tsx +++ b/src/plugins/data_view_editor/public/plugin.test.tsx @@ -24,6 +24,8 @@ import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/public/m import { DataViewEditorLazy } from './components/data_view_editor_lazy'; import { DataViewEditorPlugin } from './plugin'; +import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; + const noop = () => {}; describe('DataViewEditorPlugin', () => { @@ -31,7 +33,7 @@ describe('DataViewEditorPlugin', () => { const pluginStart = { data: dataPluginMock.createStartContract(), usageCollection: usageCollectionPluginMock.createSetupContract(), - dataViews: dataPluginMock.createStartContract().dataViews, + dataViews: dataPluginMock.createStartContract().dataViews as DataViewsServicePublic, }; let plugin: DataViewEditorPlugin; diff --git a/src/plugins/data_view_editor/public/types.ts b/src/plugins/data_view_editor/public/types.ts index b5e506db4d3e9..93fe26ab47627 100644 --- a/src/plugins/data_view_editor/public/types.ts +++ b/src/plugins/data_view_editor/public/types.ts @@ -20,7 +20,7 @@ import { EuiComboBoxOptionOption } from '@elastic/eui'; import type { DataView, - DataViewsPublicPluginStart, + DataViewsServicePublic, INDEX_PATTERN_TYPE, MatchedItem, } from '@kbn/data-views-plugin/public'; @@ -33,7 +33,7 @@ export interface DataViewEditorContext { notifications: NotificationsStart; application: ApplicationStart; overlays: OverlayStart; - dataViews: DataViewsPublicPluginStart; + dataViews: DataViewsServicePublic; searchClient: DataPublicPluginStart['search']['search']; } @@ -87,7 +87,7 @@ export interface SetupPlugins {} export interface StartPlugins { data: DataPublicPluginStart; - dataViews: DataViewsPublicPluginStart; + dataViews: DataViewsServicePublic; } export type CloseEditor = () => void; diff --git a/src/plugins/discover/kibana.json b/src/plugins/discover/kibana.json index b2a42c351a102..4d0bb971c9239 100644 --- a/src/plugins/discover/kibana.json +++ b/src/plugins/discover/kibana.json @@ -19,7 +19,8 @@ "dataViewEditor", "expressions", "unifiedFieldList", - "unifiedSearch" + "unifiedSearch", + "unifiedHistogram" ], "optionalPlugins": [ "home", diff --git a/src/plugins/discover/public/application/context/context_app.test.tsx b/src/plugins/discover/public/application/context/context_app.test.tsx index 987147403cc82..5b5fa21f12483 100644 --- a/src/plugins/discover/public/application/context/context_app.test.tsx +++ b/src/plugins/discover/public/application/context/context_app.test.tsx @@ -74,7 +74,6 @@ describe('ContextApp test', () => { const topNavProps = { appName: 'context', showSearchBar: true, - showQueryBar: true, showQueryInput: false, showFilterBar: true, showSaveQuery: false, diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index b7e3f834781cc..3146e634c4575 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -145,7 +145,6 @@ export const ContextApp = ({ dataView, anchorId }: ContextAppProps) => { return { appName: 'context', showSearchBar: true, - showQueryBar: true, showQueryInput: false, showFilterBar: true, showSaveQuery: false, diff --git a/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx b/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx deleted file mode 100644 index 155d650583899..0000000000000 --- a/src/plugins/discover/public/application/main/components/chart/discover_chart.test.tsx +++ /dev/null @@ -1,181 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { Subject, BehaviorSubject } from 'rxjs'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; -import type { DataView } from '@kbn/data-views-plugin/public'; -import { setHeaderActionMenuMounter, setUiActions } from '../../../../kibana_services'; -import { esHits } from '../../../../__mocks__/es_hits'; -import { savedSearchMock } from '../../../../__mocks__/saved_search'; -import { createSearchSourceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; -import { GetStateReturn } from '../../services/discover_state'; -import { DataCharts$, DataTotalHits$ } from '../../hooks/use_saved_search'; -import { discoverServiceMock } from '../../../../__mocks__/services'; -import { FetchStatus } from '../../../types'; -import { Chart } from './point_series'; -import { DiscoverChart } from './discover_chart'; -import { VIEW_MODE } from '../../../../components/view_mode_toggle'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { ReactWrapper } from 'enzyme'; - -setHeaderActionMenuMounter(jest.fn()); - -async function mountComponent(isTimeBased: boolean = false) { - const searchSourceMock = createSearchSourceMock({}); - const services = discoverServiceMock; - services.data.query.timefilter.timefilter.getAbsoluteTime = () => { - return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; - }; - - const totalHits$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - result: Number(esHits.length), - }) as DataTotalHits$; - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as Chart; - - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - }) as DataCharts$; - - const props = { - dataView: { - isTimeBased: () => isTimeBased, - id: '123', - getFieldByName: () => ({ type: 'date', name: 'timefield', visualizable: true }), - timeFieldName: 'timefield', - toSpec: () => ({ id: '123', timeFieldName: 'timefield' }), - } as unknown as DataView, - resetSavedSearch: jest.fn(), - savedSearch: savedSearchMock, - savedSearchDataChart$: charts$, - savedSearchDataTotalHits$: totalHits$, - savedSearchRefetch$: new Subject(), - searchSource: searchSourceMock, - state: { columns: [] }, - stateContainer: { - appStateContainer: { - getState: () => ({ - interval: 'auto', - }), - }, - } as unknown as GetStateReturn, - viewMode: VIEW_MODE.DOCUMENT_LEVEL, - setDiscoverViewMode: jest.fn(), - isTimeBased, - onResetChartHeight: jest.fn(), - }; - - let instance: ReactWrapper = {} as ReactWrapper; - await act(async () => { - instance = mountWithIntl( - - - - ); - // wait for initial async loading to complete - await new Promise((r) => setTimeout(r, 0)); - await instance.update(); - }); - return instance; -} - -describe('Discover chart', () => { - let triggerActions: unknown[] = []; - beforeEach(() => { - setUiActions({ - getTriggerCompatibleActions: () => { - return triggerActions; - }, - } as unknown as UiActionsStart); - }); - test('render without timefield', async () => { - const component = await mountComponent(); - expect(component.find('[data-test-subj="discoverChartOptionsToggle"]').exists()).toBeFalsy(); - }); - - test('render with timefield without visualize permissions', async () => { - const component = await mountComponent(true); - expect(component.find('[data-test-subj="discoverChartOptionsToggle"]').exists()).toBeTruthy(); - expect(component.find('[data-test-subj="discoverEditVisualization"]').exists()).toBeFalsy(); - }); - - test('render with timefield with visualize permissions', async () => { - triggerActions = [{}]; - const component = await mountComponent(true); - expect(component.find('[data-test-subj="discoverChartOptionsToggle"]').exists()).toBeTruthy(); - expect(component.find('[data-test-subj="discoverEditVisualization"]').exists()).toBeTruthy(); - }); - - test('triggers ui action on click', async () => { - const fn = jest.fn(); - setUiActions({ - getTrigger: () => ({ - exec: fn, - }), - getTriggerCompatibleActions: () => { - return [{}]; - }, - } as unknown as UiActionsStart); - const component = await mountComponent(true); - await act(async () => { - await component - .find('[data-test-subj="discoverEditVisualization"]') - .first() - .simulate('click'); - }); - - expect(fn).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover/public/application/main/components/chart/histogram.scss b/src/plugins/discover/public/application/main/components/chart/histogram.scss deleted file mode 100644 index c70aaeeeac7b3..0000000000000 --- a/src/plugins/discover/public/application/main/components/chart/histogram.scss +++ /dev/null @@ -1,29 +0,0 @@ -.dscChart__loading { - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 0 100%; - text-align: center; - height: 100%; - width: 100%; -} -.dscHistogram__header--partial { - font-weight: $euiFontWeightRegular; - min-width: $euiSize * 12; -} - -.dscHistogram__errorChartContainer { - padding: 0 $euiSizeS 0 $euiSizeS; -} - -.dscHistogram__errorChart { - margin-left: $euiSizeXS !important; -} - -.dscHistogram__errorChart__text { - margin-top: $euiSizeS; -} - -.dscHistogram__errorChart__icon { - padding-top: .5 * $euiSizeXS; -} diff --git a/src/plugins/discover/public/application/main/components/chart/histogram.test.tsx b/src/plugins/discover/public/application/main/components/chart/histogram.test.tsx deleted file mode 100644 index 655925e3effd7..0000000000000 --- a/src/plugins/discover/public/application/main/components/chart/histogram.test.tsx +++ /dev/null @@ -1,133 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { BehaviorSubject } from 'rxjs'; -import { FetchStatus } from '../../../types'; -import { DataCharts$ } from '../../hooks/use_saved_search'; -import { discoverServiceMock } from '../../../../__mocks__/services'; -import { Chart } from './point_series'; -import { DiscoverHistogram } from './histogram'; -import React from 'react'; -import * as hooks from '../../hooks/use_data_state'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { GetStateReturn } from '../../services/discover_state'; - -const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], -} as unknown as Chart; - -function mountComponent(fetchStatus: FetchStatus) { - const services = discoverServiceMock; - services.data.query.timefilter.timefilter.getAbsoluteTime = () => { - return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; - }; - - const charts$ = new BehaviorSubject({ - fetchStatus, - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - }) as DataCharts$; - - const timefilterUpdateHandler = jest.fn(); - - const props = { - savedSearchData$: charts$, - timefilterUpdateHandler, - stateContainer: { - appStateContainer: { - getState: () => ({ - interval: 'auto', - }), - }, - } as unknown as GetStateReturn, - }; - - return mountWithIntl( - - - - ); -} - -describe('Histogram', () => { - it('renders correctly', () => { - jest.spyOn(hooks, 'useDataState').mockImplementation(() => ({ - fetchStatus: FetchStatus.COMPLETE, - chartData, - bucketInterval: { - scaled: true, - description: 'Bucket interval', - scale: 1, - }, - })); - const component = mountComponent(FetchStatus.COMPLETE); - expect(component.find('[data-test-subj="discoverChart"]').exists()).toBe(true); - }); - - it('renders error correctly', () => { - jest.spyOn(hooks, 'useDataState').mockImplementation(() => ({ - fetchStatus: FetchStatus.ERROR, - error: new Error('Loading error'), - })); - const component = mountComponent(FetchStatus.ERROR); - expect(component.find('[data-test-subj="discoverChart"]').exists()).toBe(false); - expect(component.find('.dscHistogram__errorChartContainer').exists()).toBe(true); - expect(component.find('.dscHistogram__errorChart__text').get(1).props.children).toBe( - 'Loading error' - ); - }); - - it('renders loading state correctly', () => { - jest.spyOn(hooks, 'useDataState').mockImplementation(() => ({ - fetchStatus: FetchStatus.LOADING, - chartData: null, - })); - const component = mountComponent(FetchStatus.LOADING); - expect(component.find('[data-test-subj="discoverChart"]').exists()).toBe(true); - expect(component.find('.dscChart__loading').exists()).toBe(true); - }); -}); diff --git a/src/plugins/discover/public/application/main/components/chart/point_series.ts b/src/plugins/discover/public/application/main/components/chart/point_series.ts deleted file mode 100644 index c8795296d6fd8..0000000000000 --- a/src/plugins/discover/public/application/main/components/chart/point_series.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { uniq } from 'lodash'; -import { Duration, Moment } from 'moment'; -import { Unit } from '@kbn/datemath'; -import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; - -export interface Column { - id: string; - name: string; -} - -export interface Row { - [key: string]: number | 'NaN'; -} - -export interface Table { - columns: Column[]; - rows: Row[]; -} - -export interface HistogramParamsBounds { - min: Moment; - max: Moment; -} - -interface HistogramParams { - date: true; - interval: Duration; - intervalESValue: number; - intervalESUnit: Unit; - format: string; - bounds: HistogramParamsBounds; -} -export interface Dimension { - accessor: 0 | 1; - format: SerializedFieldFormat<{ pattern: string }>; - label: string; -} - -export interface Dimensions { - x: Dimension & { params: HistogramParams }; - y: Dimension; -} - -interface Ordered { - date: true; - interval: Duration; - intervalESUnit: string; - intervalESValue: number; - min: Moment; - max: Moment; -} -export interface Chart { - values: Array<{ - x: number; - y: number; - }>; - xAxisOrderedValues: number[]; - xAxisFormat: Dimension['format']; - yAxisFormat: Dimension['format']; - xAxisLabel: Column['name']; - yAxisLabel?: Column['name']; - ordered: Ordered; -} - -export const buildPointSeriesData = (table: Table, dimensions: Dimensions): Chart => { - const { x, y } = dimensions; - const xAccessor = table.columns[x.accessor].id; - const yAccessor = table.columns[y.accessor].id; - const chart = {} as Chart; - - chart.xAxisOrderedValues = uniq(table.rows.map((r) => r[xAccessor] as number)); - chart.xAxisFormat = x.format; - chart.xAxisLabel = table.columns[x.accessor].name; - chart.yAxisFormat = y.format; - const { intervalESUnit, intervalESValue, interval, bounds } = x.params; - chart.ordered = { - date: true, - interval, - intervalESUnit, - intervalESValue, - min: bounds.min, - max: bounds.max, - }; - - chart.yAxisLabel = table.columns[y.accessor].name; - - chart.values = table.rows - .filter((row) => row && row[yAccessor] !== 'NaN') - .map((row) => ({ - x: row[xAccessor] as number, - y: row[yAccessor] as number, - })); - - return chart; -}; diff --git a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.scss b/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.scss deleted file mode 100644 index 5a3999f129bf4..0000000000000 --- a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.scss +++ /dev/null @@ -1,3 +0,0 @@ -.dscHitsCounter { - flex-grow: 0; -} diff --git a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.test.tsx b/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.test.tsx deleted file mode 100644 index b8111b25a6ef2..0000000000000 --- a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.test.tsx +++ /dev/null @@ -1,71 +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 - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { ReactWrapper } from 'enzyme'; -import { HitsCounter, HitsCounterProps } from './hits_counter'; -import { findTestSubject } from '@elastic/eui/lib/test'; -import { BehaviorSubject } from 'rxjs'; -import { FetchStatus } from '../../../types'; -import { DataTotalHits$ } from '../../hooks/use_saved_search'; - -describe('hits counter', function () { - let props: HitsCounterProps; - let component: ReactWrapper; - - beforeAll(() => { - props = { - onResetQuery: jest.fn(), - showResetButton: true, - savedSearchData$: new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - result: 2, - }) as DataTotalHits$, - }; - }); - - it('HitsCounter renders a button by providing the showResetButton property', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(1); - }); - - it('HitsCounter not renders a button when the showResetButton property is false', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(0); - }); - - it('expect to render the number of hits', function () { - component = mountWithIntl(); - const hits = findTestSubject(component, 'discoverQueryHits'); - expect(hits.text()).toBe('2'); - }); - - it('expect to render 1,899 hits if 1899 hits given', function () { - const data$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - result: 1899, - }) as DataTotalHits$; - component = mountWithIntl( - - ); - const hits = findTestSubject(component, 'discoverQueryHits'); - expect(hits.text()).toBe('1,899'); - }); - - it('should reset query', function () { - component = mountWithIntl(); - findTestSubject(component, 'resetSavedSearch').simulate('click'); - expect(props.onResetQuery).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.tsx b/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.tsx deleted file mode 100644 index bb7681c2efa36..0000000000000 --- a/src/plugins/discover/public/application/main/components/hits_counter/hits_counter.tsx +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import './hits_counter.scss'; -import React from 'react'; -import { - EuiButtonEmpty, - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiLoadingSpinner, -} from '@elastic/eui'; -import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react'; -import { i18n } from '@kbn/i18n'; -import { DataTotalHits$, DataTotalHitsMsg } from '../../hooks/use_saved_search'; -import { FetchStatus } from '../../../types'; -import { useDataState } from '../../hooks/use_data_state'; - -export interface HitsCounterProps { - /** - * displays the reset button - */ - showResetButton: boolean; - /** - * resets the query - */ - onResetQuery: () => void; - /** - * saved search data observable - */ - savedSearchData$: DataTotalHits$; -} - -export function HitsCounter({ showResetButton, onResetQuery, savedSearchData$ }: HitsCounterProps) { - const data: DataTotalHitsMsg = useDataState(savedSearchData$); - - const hits = data.result || 0; - if (!hits && data.fetchStatus === FetchStatus.LOADING) { - return null; - } - - const formattedHits = ( - - - - ); - - return ( - - - - {data.fetchStatus === FetchStatus.PARTIAL && ( - - )} - {data.fetchStatus !== FetchStatus.PARTIAL && ( - - )} - - - {data.fetchStatus === FetchStatus.PARTIAL && ( - - - - )} - {showResetButton && ( - - - - - - )} - - ); -} diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index a4c9227a2c072..f78ed164493a5 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -11,6 +11,7 @@ import { SearchSource } from '@kbn/data-plugin/common'; import { BehaviorSubject, Subject } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { action } from '@storybook/addon-actions'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { FetchStatus } from '../../../../types'; import { AvailableFields$, @@ -22,50 +23,10 @@ import { } from '../../../hooks/use_saved_search'; import { buildDataTableRecordList } from '../../../../../utils/build_data_record'; import { esHits } from '../../../../../__mocks__/es_hits'; -import { Chart } from '../../chart/point_series'; import { SavedSearch } from '../../../../..'; import { DiscoverLayoutProps } from '../types'; import { GetStateReturn } from '../../../services/discover_state'; -const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: () => 1000, - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], -} as unknown as Chart; - const documentObservables = { main$: new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, @@ -89,12 +50,7 @@ const documentObservables = { charts$: new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, + response: {} as unknown as SearchResponse, }) as DataCharts$, }; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index dfff574659744..2aacf598e58c4 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -28,7 +28,7 @@ import { HIDE_ANNOUNCEMENTS, } from '../../../../../common'; import { useColumns } from '../../../../hooks/use_data_grid_columns'; -import { DataDocuments$, DataDocumentsMsg, RecordRawType } from '../../hooks/use_saved_search'; +import { DataDocuments$, RecordRawType } from '../../hooks/use_saved_search'; import { AppState, GetStateReturn } from '../../services/discover_state'; import { useDataState } from '../../hooks/use_data_state'; import { DocTableInfinite } from '../../../../components/doc_table/doc_table_infinite'; @@ -84,7 +84,7 @@ function DiscoverDocumentsComponent({ const isLegacy = useMemo(() => uiSettings.get(DOC_TABLE_LEGACY), [uiSettings]); const sampleSize = useMemo(() => uiSettings.get(SAMPLE_SIZE_SETTING), [uiSettings]); - const documentState: DataDocumentsMsg = useDataState(documents$); + const documentState = useDataState(documents$); const isLoading = documentState.fetchStatus === FetchStatus.LOADING; const isPlainRecord = useMemo( () => getRawRecordType(state.query) === RecordRawType.PLAIN, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss index ee727779fc2a1..70963f50b96a7 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss @@ -53,44 +53,6 @@ discover-app { height: auto; } -.dscResultCount { - padding: $euiSizeS; - min-height: $euiSize * 3; - - @include euiBreakpoint('xs', 's') { - .dscResultCount__toggle { - align-items: flex-end; - } - - .dscResultCount__title, - .dscResultCount__actions { - margin-bottom: 0 !important; - } - } -} - -.dscTimechart { - flex-grow: 1; - display: flex; - flex-direction: column; - position: relative; - - // SASSTODO: the visualizing component should have an option or a modifier - .series > rect { - fill-opacity: .5; - stroke-width: 1; - } -} - -.dscHistogram { - flex-grow: 1; - padding: 0 $euiSizeS $euiSizeS $euiSizeS; -} - -.dscHistogramTimeRange { - padding: 0 $euiSizeS 0 $euiSizeS; -} - .dscTable { // needs for scroll container of lagacy table min-height: 0; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index 32aa0b0999bbe..0e9c7f8449520 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -31,16 +31,72 @@ import { import { discoverServiceMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { Chart } from '../chart/point_series'; import { DiscoverSidebar } from '../sidebar/discover_sidebar'; import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { DiscoverServices } from '../../../../build_services'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; +import type { UnifiedHistogramChartData } from '@kbn/unified-histogram-plugin/public'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { setTimeout } from 'timers/promises'; +import { act } from 'react-dom/test-utils'; -setHeaderActionMenuMounter(jest.fn()); +jest.mock('@kbn/unified-histogram-plugin/public', () => { + const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); + + const chartData = { + xAxisOrderedValues: [ + 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, + 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, + 1624917600000, 1625004000000, 1625090400000, + ], + xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, + xAxisLabel: 'order_date per day', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: { + asMilliseconds: jest.fn(), + }, + intervalESUnit: 'd', + intervalESValue: 1, + min: '2021-03-18T08:28:56.411Z', + max: '2021-07-01T07:28:56.411Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1623880800000, y: 134 }, + { x: 1623967200000, y: 152 }, + { x: 1624053600000, y: 141 }, + { x: 1624140000000, y: 138 }, + { x: 1624226400000, y: 142 }, + { x: 1624312800000, y: 157 }, + { x: 1624399200000, y: 149 }, + { x: 1624485600000, y: 146 }, + { x: 1624572000000, y: 170 }, + { x: 1624658400000, y: 137 }, + { x: 1624744800000, y: 150 }, + { x: 1624831200000, y: 144 }, + { x: 1624917600000, y: 147 }, + { x: 1625004000000, y: 137 }, + { x: 1625090400000, y: 66 }, + ], + } as unknown as UnifiedHistogramChartData; + + return { + ...originalModule, + buildChartData: jest.fn().mockImplementation(() => ({ + chartData, + bucketInterval: { + scaled: true, + description: 'test', + scale: 2, + }, + })), + }; +}); function getAppStateContainer() { const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; @@ -51,7 +107,9 @@ function getAppStateContainer() { return appStateContainer; } -function mountComponent( +setHeaderActionMenuMounter(jest.fn()); + +async function mountComponent( dataView: DataView, prevSidebarClosed?: boolean, mountOptions: { attachTo?: HTMLElement } = {}, @@ -92,53 +150,9 @@ function mountComponent( result: Number(esHits.length), }) as DataTotalHits$; - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as Chart; - const charts$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, + response: {} as unknown as SearchResponse, }) as DataCharts$; const savedSearchData$ = { @@ -176,7 +190,7 @@ function mountComponent( adHocDataViewList: [], }; - return mountWithIntl( + const component = mountWithIntl( @@ -184,37 +198,49 @@ function mountComponent( , mountOptions ); + + // DiscoverMainContent uses UnifiedHistogramLayout which + // is lazy loaded, so we need to wait for it to be loaded + await act(() => setTimeout(0)); + + return component; } describe('Discover component', () => { - test('selected data view without time field displays no chart toggle', () => { + test('selected data view without time field displays no chart toggle', async () => { const container = document.createElement('div'); - mountComponent(dataViewMock, undefined, { attachTo: container }); - expect(container.querySelector('[data-test-subj="discoverChartOptionsToggle"]')).toBeNull(); + await mountComponent(dataViewMock, undefined, { attachTo: container }); + expect( + container.querySelector('[data-test-subj="unifiedHistogramChartOptionsToggle"]') + ).toBeNull(); }); - test('selected data view with time field displays chart toggle', () => { + test('selected data view with time field displays chart toggle', async () => { const container = document.createElement('div'); - mountComponent(dataViewWithTimefieldMock, undefined, { attachTo: container }); - expect(container.querySelector('[data-test-subj="discoverChartOptionsToggle"]')).not.toBeNull(); + await mountComponent(dataViewWithTimefieldMock, undefined, { attachTo: container }); + expect( + container.querySelector('[data-test-subj="unifiedHistogramChartOptionsToggle"]') + ).not.toBeNull(); }); - test('sql query displays no chart toggle', () => { + test('sql query displays no chart toggle', async () => { const container = document.createElement('div'); - mountComponent( + await mountComponent( dataViewWithTimefieldMock, false, { attachTo: container }, { sql: 'SELECT * FROM test' }, true ); - expect(container.querySelector('[data-test-subj="discoverChartOptionsToggle"]')).toBeNull(); + expect( + container.querySelector('[data-test-subj="unifiedHistogramChartOptionsToggle"]') + ).toBeNull(); }); - test('the saved search title h1 gains focus on navigate', () => { + test('the saved search title h1 gains focus on navigate', async () => { const container = document.createElement('div'); document.body.appendChild(container); - const component = mountComponent(dataViewWithTimefieldMock, undefined, { + const component = await mountComponent(dataViewWithTimefieldMock, undefined, { attachTo: container, }); expect( @@ -223,18 +249,18 @@ describe('Discover component', () => { }); describe('sidebar', () => { - test('should be opened if discover:sidebarClosed was not set', () => { - const component = mountComponent(dataViewWithTimefieldMock, undefined); + test('should be opened if discover:sidebarClosed was not set', async () => { + const component = await mountComponent(dataViewWithTimefieldMock, undefined); expect(component.find(DiscoverSidebar).length).toBe(1); }); - test('should be opened if discover:sidebarClosed is false', () => { - const component = mountComponent(dataViewWithTimefieldMock, false); + test('should be opened if discover:sidebarClosed is false', async () => { + const component = await mountComponent(dataViewWithTimefieldMock, false); expect(component.find(DiscoverSidebar).length).toBe(1); }); - test('should be closed if discover:sidebarClosed is true', () => { - const component = mountComponent(dataViewWithTimefieldMock, true); + test('should be closed if discover:sidebarClosed is true', async () => { + const component = await mountComponent(dataViewWithTimefieldMock, true); expect(component.find(DiscoverSidebar).length).toBe(0); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index 6f66b1f613b22..54e3fa0b19ca5 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { Subject, BehaviorSubject } from 'rxjs'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; @@ -23,36 +23,92 @@ import { } from '../../hooks/use_saved_search'; import { discoverServiceMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; -import { Chart } from '../chart/point_series'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; -import { - DiscoverMainContent, - DiscoverMainContentProps, - HISTOGRAM_HEIGHT_KEY, -} from './discover_main_content'; -import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; -import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels'; -import { euiThemeVars } from '@kbn/ui-theme'; +import { DiscoverMainContent, DiscoverMainContentProps } from './discover_main_content'; +import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; import { CoreTheme } from '@kbn/core/public'; import { act } from 'react-dom/test-utils'; import { setTimeout } from 'timers/promises'; -import { DiscoverChart } from '../chart'; -import { ReactWrapper } from 'enzyme'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; +import { + UnifiedHistogramChartData, + UnifiedHistogramLayout, +} from '@kbn/unified-histogram-plugin/public'; +import { HISTOGRAM_HEIGHT_KEY } from './use_discover_histogram'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; + +jest.mock('@kbn/unified-histogram-plugin/public', () => { + const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); + + const chartData = { + xAxisOrderedValues: [ + 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, + 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, + 1624917600000, 1625004000000, 1625090400000, + ], + xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, + xAxisLabel: 'order_date per day', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: { + asMilliseconds: jest.fn(), + }, + intervalESUnit: 'd', + intervalESValue: 1, + min: '2021-03-18T08:28:56.411Z', + max: '2021-07-01T07:28:56.411Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1623880800000, y: 134 }, + { x: 1623967200000, y: 152 }, + { x: 1624053600000, y: 141 }, + { x: 1624140000000, y: 138 }, + { x: 1624226400000, y: 142 }, + { x: 1624312800000, y: 157 }, + { x: 1624399200000, y: 149 }, + { x: 1624485600000, y: 146 }, + { x: 1624572000000, y: 170 }, + { x: 1624658400000, y: 137 }, + { x: 1624744800000, y: 150 }, + { x: 1624831200000, y: 144 }, + { x: 1624917600000, y: 147 }, + { x: 1625004000000, y: 137 }, + { x: 1625090400000, y: 66 }, + ], + } as unknown as UnifiedHistogramChartData; + + return { + ...originalModule, + buildChartData: jest.fn().mockImplementation(() => ({ + chartData, + bucketInterval: { + scaled: true, + description: 'test', + scale: 2, + }, + })), + }; +}); const mountComponent = async ({ isPlainRecord = false, hideChart = false, isTimeBased = true, storage, + savedSearch = savedSearchMock, + resetSavedSearch = jest.fn(), }: { isPlainRecord?: boolean; hideChart?: boolean; isTimeBased?: boolean; storage?: Storage; + savedSearch?: SavedSearch; + resetSavedSearch?: () => void; } = {}) => { let services = discoverServiceMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { @@ -84,53 +140,9 @@ const mountComponent = async ({ result: Number(esHits.length), }) as DataTotalHits$; - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as Chart; - const charts$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, + response: {} as unknown as SearchResponse, }) as DataCharts$; const savedSearchData$ = { @@ -145,9 +157,9 @@ const mountComponent = async ({ isPlainRecord, dataView: dataViewMock, navigateTo: jest.fn(), - resetSavedSearch: jest.fn(), + resetSavedSearch, setExpandedDoc: jest.fn(), - savedSearch: savedSearchMock, + savedSearch, savedSearchData$, savedSearchRefetch$: new Subject(), state: { columns: [], hideChart }, @@ -177,109 +189,30 @@ const mountComponent = async ({ ); - // useIsWithinBreakpoints triggers state updates which cause act - // issues and prevent our resize events from being fired correctly - // https://github.com/enzymejs/enzyme/issues/2073 + // DiscoverMainContent uses UnifiedHistogramLayout which + // is lazy loaded, so we need to wait for it to be loaded await act(() => setTimeout(0)); return component; }; -const setWindowWidth = (component: ReactWrapper, width: string) => { - window.innerWidth = parseInt(width, 10); - act(() => { - window.dispatchEvent(new Event('resize')); - }); - component.update(); -}; - describe('Discover main content component', () => { - const windowWidth = window.innerWidth; - - beforeEach(() => { - window.innerWidth = windowWidth; - }); - - describe('DISCOVER_PANELS_MODE', () => { - it('should set the panels mode to DISCOVER_PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.m); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.RESIZABLE); - }); - - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED when viewing on small screens and below', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); - - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if hideChart is true', async () => { - const component = await mountComponent({ hideChart: true }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); - - it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if isTimeBased is false', async () => { - const component = await mountComponent({ isTimeBased: false }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED); - }); - - it('should set the panels mode to DISCOVER_PANELS_MODE.SINGLE if isPlainRecord is true', async () => { - const component = await mountComponent({ isPlainRecord: true }); - expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.SINGLE); - }); - - it('should set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is false', async () => { - const component = await mountComponent(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).toHaveStyle({ - height: `${expectedHeight}px`, - }); - }); - - it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is true', async () => { - const component = await mountComponent({ hideChart: true }); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ - height: `${expectedHeight}px`, - }); - }); - - it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and isTimeBased is false', async () => { - const component = await mountComponent({ isTimeBased: false }); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight'); - expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({ - height: `${expectedHeight}px`, - }); - }); - - it('should pass undefined for onResetChartHeight to DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const topPanelHeight = 123; - storage.get = jest.fn().mockImplementation(() => topPanelHeight); - const component = await mountComponent({ storage }); - expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeDefined(); - setWindowWidth(component, euiThemeVars.euiBreakpoints.s); - expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeUndefined(); - }); - }); - describe('DocumentViewModeToggle', () => { it('should show DocumentViewModeToggle when isPlainRecord is false', async () => { const component = await mountComponent(); + component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(true); }); it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => { const component = await mountComponent({ isPlainRecord: true }); + component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(false); }); }); describe('topPanelHeight persistence', () => { - it('should try to get the initial topPanelHeight for DiscoverPanels from storage', async () => { + it('should try to get the initial topPanelHeight for UnifiedHistogramLayout from storage', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; const originalGet = storage.get; storage.get = jest.fn().mockImplementation(originalGet); @@ -287,77 +220,62 @@ describe('Discover main content component', () => { expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); }); - it('should pass a default topPanelHeight to DiscoverPanels if no value is found in storage', async () => { + it('should pass undefined to UnifiedHistogramLayout if no value is found in storage', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; const originalGet = storage.get; storage.get = jest.fn().mockImplementation(originalGet); const component = await mountComponent({ storage }); expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); expect(storage.get).toHaveReturnedWith(null); - expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBeGreaterThan(0); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(undefined); }); - it('should pass the stored topPanelHeight to DiscoverPanels if a value is found in storage', async () => { + it('should pass the stored topPanelHeight to UnifiedHistogramLayout if a value is found in storage', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; const topPanelHeight = 123; storage.get = jest.fn().mockImplementation(() => topPanelHeight); const component = await mountComponent({ storage }); expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); expect(storage.get).toHaveReturnedWith(topPanelHeight); - expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(topPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(topPanelHeight); }); - it('should update the topPanelHeight in storage and pass the new value to DiscoverPanels when the topPanelHeight changes', async () => { + it('should update the topPanelHeight in storage and pass the new value to UnifiedHistogramLayout when the topPanelHeight changes', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; const originalSet = storage.set; storage.set = jest.fn().mockImplementation(originalSet); const component = await mountComponent({ storage }); const newTopPanelHeight = 123; - expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).not.toBe( + newTopPanelHeight + ); act(() => { - component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight); + component.find(UnifiedHistogramLayout).prop('onTopPanelHeightChange')!(newTopPanelHeight); }); component.update(); expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); - expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(newTopPanelHeight); }); + }); - it('should reset the topPanelHeight to the default when onResetChartHeight is called on DiscoverChart', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalSet = storage.set; - storage.set = jest.fn().mockImplementation(originalSet); - const component = await mountComponent({ storage }); - const defaultTopPanelHeight = component.find(DiscoverPanels).prop('topPanelHeight'); - const newTopPanelHeight = 123; - expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight); - act(() => { - component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight); - }); - component.update(); - expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); - expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight); - act(() => { - component.find(DiscoverChart).prop('onResetChartHeight')!(); - }); - component.update(); - expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, defaultTopPanelHeight); - expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(defaultTopPanelHeight); + describe('reset search button', () => { + it('renders the button when there is a saved search', async () => { + const component = await mountComponent(); + expect(findTestSubject(component, 'resetSavedSearch').length).toBe(1); }); - it('should pass undefined for onResetChartHeight to DiscoverChart when the chart is the default height', async () => { - const component = await mountComponent(); - const defaultTopPanelHeight = component.find(DiscoverPanels).prop('topPanelHeight'); - const newTopPanelHeight = 123; - act(() => { - component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight); + it('does not render the button when there is no saved search', async () => { + const component = await mountComponent({ + savedSearch: { ...savedSearchMock, id: undefined }, }); - component.update(); - expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeDefined(); - act(() => { - component.find(DiscoverPanels).prop('onTopPanelHeightChange')(defaultTopPanelHeight); - }); - component.update(); - expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeUndefined(); + expect(findTestSubject(component, 'resetSavedSearch').length).toBe(0); + }); + + it('should call resetSavedSearch when clicked', async () => { + const resetSavedSearch = jest.fn(); + const component = await mountComponent({ resetSavedSearch }); + findTestSubject(component, 'resetSavedSearch').simulate('click'); + expect(resetSavedSearch).toHaveBeenCalled(); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index 4998e561f5dd7..100412c8f7930 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -6,37 +6,27 @@ * Side Public License, v 1. */ -import { - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiSpacer, - useEuiTheme, - useIsWithinBreakpoints, -} from '@elastic/eui'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import React, { RefObject, useCallback, useMemo, useState } from 'react'; +import React, { RefObject, useCallback } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { METRIC_TYPE } from '@kbn/analytics'; -import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal'; -import { css } from '@emotion/css'; +import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DataTableRecord } from '../../../../types'; import { DocumentViewModeToggle, VIEW_MODE } from '../../../../components/view_mode_toggle'; import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types'; import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; import { AppState, GetStateReturn } from '../../services/discover_state'; -import { DiscoverChart } from '../chart'; import { FieldStatisticsTable } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; import { DOCUMENTS_VIEW_CLICK, FIELD_STATISTICS_VIEW_CLICK } from '../field_stats_table/constants'; -import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels'; +import { useDiscoverHistogram } from './use_discover_histogram'; -const DiscoverChartMemoized = React.memo(DiscoverChart); const FieldStatisticsTableMemoized = React.memo(FieldStatisticsTable); -export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight'; - export interface DiscoverMainContentProps { isPlainRecord: boolean; dataView: DataView; @@ -76,7 +66,8 @@ export const DiscoverMainContent = ({ columns, resizeRef, }: DiscoverMainContentProps) => { - const { trackUiMetric, storage } = useDiscoverServices(); + const services = useDiscoverServices(); + const { trackUiMetric } = services; const setDiscoverViewMode = useCallback( (mode: VIEW_MODE) => { @@ -93,139 +84,98 @@ export const DiscoverMainContent = ({ [trackUiMetric, stateContainer] ); - const topPanelNode = useMemo( - () => createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } }), - [] - ); - - const mainPanelNode = useMemo( - () => createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } }), - [] - ); - - const hideChart = state.hideChart || !isTimeBased; - const showFixedPanels = useIsWithinBreakpoints(['xs', 's']) || isPlainRecord || hideChart; - const { euiTheme } = useEuiTheme(); - const defaultTopPanelHeight = euiTheme.base * 12; - const minTopPanelHeight = euiTheme.base * 8; - const minMainPanelHeight = euiTheme.base * 10; - - const [topPanelHeight, setTopPanelHeight] = useState( - Number(storage.get(HISTOGRAM_HEIGHT_KEY)) || defaultTopPanelHeight - ); - - const storeTopPanelHeight = useCallback( - (newTopPanelHeight: number) => { - storage.set(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); - setTopPanelHeight(newTopPanelHeight); - }, - [storage] - ); - - const resetTopPanelHeight = useCallback( - () => storeTopPanelHeight(defaultTopPanelHeight), - [storeTopPanelHeight, defaultTopPanelHeight] - ); - - const onTopPanelHeightChange = useCallback( - (newTopPanelHeight: number) => storeTopPanelHeight(newTopPanelHeight), - [storeTopPanelHeight] - ); - - const chartClassName = - showFixedPanels && !hideChart - ? css` - height: ${defaultTopPanelHeight}px; - ` - : 'eui-fullHeight'; - - const panelsMode = isPlainRecord - ? DISCOVER_PANELS_MODE.SINGLE - : showFixedPanels - ? DISCOVER_PANELS_MODE.FIXED - : DISCOVER_PANELS_MODE.RESIZABLE; + const { + topPanelHeight, + hits, + chart, + onEditVisualization, + onTopPanelHeightChange, + onChartHiddenChange, + onTimeIntervalChange, + } = useDiscoverHistogram({ + stateContainer, + state, + savedSearchData$, + dataView, + savedSearch, + isTimeBased, + isPlainRecord, + }); return ( - <> - - : } - onResetChartHeight={ - topPanelHeight !== defaultTopPanelHeight && - panelsMode === DISCOVER_PANELS_MODE.RESIZABLE - ? resetTopPanelHeight - : undefined - } - /> - - - - {!isPlainRecord && ( - - {!showFixedPanels && } - - + + - - )} - {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( - - ) : ( - - )} - - - } - mainPanel={} - onTopPanelHeightChange={onTopPanelHeightChange} - /> - + + + ) : undefined + } + onTopPanelHeightChange={onTopPanelHeightChange} + onEditVisualization={onEditVisualization} + onChartHiddenChange={onChartHiddenChange} + onTimeIntervalChange={onTimeIntervalChange} + > + + {!isPlainRecord && ( + + + + + )} + {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( + + ) : ( + + )} + + ); }; diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts new file mode 100644 index 0000000000000..12fde6a5b1061 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts @@ -0,0 +1,297 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { buildDataTableRecord } from '../../../../utils/build_data_record'; +import { esHits } from '../../../../__mocks__/es_hits'; +import { act, renderHook } from '@testing-library/react-hooks'; +import { BehaviorSubject } from 'rxjs'; +import { FetchStatus } from '../../../types'; +import { + AvailableFields$, + DataCharts$, + DataDocuments$, + DataMain$, + DataTotalHits$, + RecordRawType, +} from '../../hooks/use_saved_search'; +import type { GetStateReturn } from '../../services/discover_state'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; +import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { dataViewWithTimefieldMock } from '../../../../__mocks__/data_view_with_timefield'; +import { + CHART_HIDDEN_KEY, + HISTOGRAM_HEIGHT_KEY, + useDiscoverHistogram, +} from './use_discover_histogram'; +import { setTimeout } from 'timers/promises'; +import { calculateBounds } from '@kbn/data-plugin/public'; + +const mockData = dataPluginMock.createStartContract(); + +mockData.query.timefilter.timefilter.getTime = () => { + return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; +}; +mockData.query.timefilter.timefilter.calculateBounds = (timeRange) => { + return calculateBounds(timeRange); +}; + +let mockStorage = new LocalStorageMock({}) as unknown as Storage; +let mockCanVisualize = true; + +jest.mock('../../../../hooks/use_discover_services', () => { + const originalModule = jest.requireActual('../../../../hooks/use_discover_services'); + return { + ...originalModule, + useDiscoverServices: () => ({ storage: mockStorage, data: mockData }), + }; +}); + +jest.mock('@kbn/unified-field-list-plugin/public', () => { + const originalModule = jest.requireActual('@kbn/unified-field-list-plugin/public'); + return { + ...originalModule, + getVisualizeInformation: jest.fn(() => Promise.resolve(mockCanVisualize)), + }; +}); + +describe('useDiscoverHistogram', () => { + const renderUseDiscoverHistogram = async ({ + isPlainRecord = false, + isTimeBased = true, + canVisualize = true, + storage = new LocalStorageMock({}) as unknown as Storage, + stateContainer = {}, + }: { + isPlainRecord?: boolean; + isTimeBased?: boolean; + canVisualize?: boolean; + storage?: Storage; + stateContainer?: unknown; + } = {}) => { + mockStorage = storage; + mockCanVisualize = canVisualize; + + const main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$; + + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewWithTimefieldMock)), + }) as DataDocuments$; + + const availableFields$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$; + + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: Number(esHits.length), + }) as DataTotalHits$; + + const charts$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + response: { + took: 0, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: 29, + max_score: null, + hits: [], + }, + aggregations: { + '2': { + buckets: [ + { + key_as_string: '2022-10-05T16:00:00.000-03:00', + key: 1664996400000, + doc_count: 6, + }, + { + key_as_string: '2022-10-05T16:30:00.000-03:00', + key: 1664998200000, + doc_count: 2, + }, + { + key_as_string: '2022-10-05T17:00:00.000-03:00', + key: 1665000000000, + doc_count: 3, + }, + { + key_as_string: '2022-10-05T17:30:00.000-03:00', + key: 1665001800000, + doc_count: 8, + }, + { + key_as_string: '2022-10-05T18:00:00.000-03:00', + key: 1665003600000, + doc_count: 10, + }, + ], + }, + }, + } as SearchResponse, + }) as DataCharts$; + + const savedSearchData$ = { + main$, + documents$, + totalHits$, + charts$, + availableFields$, + }; + + const hook = renderHook(() => { + return useDiscoverHistogram({ + stateContainer: stateContainer as GetStateReturn, + state: { interval: 'auto', hideChart: false }, + savedSearchData$, + dataView: dataViewWithTimefieldMock, + savedSearch: savedSearchMock, + isTimeBased, + isPlainRecord, + }); + }); + + await act(() => setTimeout(0)); + + return hook; + }; + + const expectedChartData = { + xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], + xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, + xAxisLabel: 'timestamp per 0 milliseconds', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: 'P0D', + intervalESUnit: 'ms', + intervalESValue: 0, + min: '1991-03-29T08:04:00.694Z', + max: '2021-03-29T07:04:00.695Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1664996400000, y: 6 }, + { x: 1664998200000, y: 2 }, + { x: 1665000000000, y: 3 }, + { x: 1665001800000, y: 8 }, + { x: 1665003600000, y: 10 }, + ], + }; + + describe('contexts', () => { + it('should output the correct hits context', async () => { + const { result } = await renderUseDiscoverHistogram(); + expect(result.current.hits?.status).toBe(FetchStatus.COMPLETE); + expect(result.current.hits?.total).toEqual(esHits.length); + }); + + it('should output the correct chart context', async () => { + const { result } = await renderUseDiscoverHistogram(); + expect(result.current.chart?.status).toBe(FetchStatus.COMPLETE); + expect(result.current.chart?.hidden).toBe(false); + expect(result.current.chart?.timeInterval).toBe('auto'); + expect(result.current.chart?.bucketInterval?.toString()).toBe('P0D'); + expect(JSON.stringify(result.current.chart?.data)).toBe(JSON.stringify(expectedChartData)); + expect(result.current.chart?.error).toBeUndefined(); + }); + + it('should output undefined for hits and chart if isPlainRecord is true', async () => { + const { result } = await renderUseDiscoverHistogram({ isPlainRecord: true }); + expect(result.current.hits).toBeUndefined(); + expect(result.current.chart).toBeUndefined(); + }); + + it('should output undefined for chart if isTimeBased is false', async () => { + const { result } = await renderUseDiscoverHistogram({ isTimeBased: false }); + expect(result.current.hits).not.toBeUndefined(); + expect(result.current.chart).toBeUndefined(); + }); + }); + + describe('onEditVisualization', () => { + it('returns a callback for onEditVisualization when the data view can be visualized', async () => { + const { result } = await renderUseDiscoverHistogram(); + expect(result.current.onEditVisualization).toBeDefined(); + }); + + it('returns undefined for onEditVisualization when the data view cannot be visualized', async () => { + const { result } = await renderUseDiscoverHistogram({ canVisualize: false }); + expect(result.current.onEditVisualization).toBeUndefined(); + }); + }); + + describe('topPanelHeight', () => { + it('should try to get the topPanelHeight from storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + storage.get = jest.fn(() => 100); + const { result } = await renderUseDiscoverHistogram({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(result.current.topPanelHeight).toBe(100); + }); + + it('should update topPanelHeight when onTopPanelHeightChange is called', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + storage.get = jest.fn(() => 100); + storage.set = jest.fn(); + const { result } = await renderUseDiscoverHistogram({ storage }); + expect(result.current.topPanelHeight).toBe(100); + act(() => { + result.current.onTopPanelHeightChange(200); + }); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, 200); + expect(result.current.topPanelHeight).toBe(200); + }); + }); + + describe('callbacks', () => { + it('should update chartHidden when onChartHiddenChange is called', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + storage.set = jest.fn(); + const stateContainer = { + setAppState: jest.fn(), + }; + const { result } = await renderUseDiscoverHistogram({ + storage, + stateContainer, + }); + act(() => { + result.current.onChartHiddenChange(true); + }); + expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, true); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: true }); + }); + + it('should update interval when onTimeIntervalChange is called', async () => { + const stateContainer = { + setAppState: jest.fn(), + }; + const { result } = await renderUseDiscoverHistogram({ + stateContainer, + }); + act(() => { + result.current.onTimeIntervalChange('auto'); + }); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ interval: 'auto' }); + }); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts new file mode 100644 index 0000000000000..3032fa13af043 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { + getVisualizeInformation, + triggerVisualizeActions, +} from '@kbn/unified-field-list-plugin/public'; +import { buildChartData } from '@kbn/unified-histogram-plugin/public'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { getUiActions } from '../../../../kibana_services'; +import { PLUGIN_ID } from '../../../../../common'; +import { useDiscoverServices } from '../../../../hooks/use_discover_services'; +import { useDataState } from '../../hooks/use_data_state'; +import type { SavedSearchData } from '../../hooks/use_saved_search'; +import type { AppState, GetStateReturn } from '../../services/discover_state'; + +export const CHART_HIDDEN_KEY = 'discover:chartHidden'; +export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight'; + +export const useDiscoverHistogram = ({ + stateContainer, + state, + savedSearchData$, + dataView, + savedSearch, + isTimeBased, + isPlainRecord, +}: { + stateContainer: GetStateReturn; + state: AppState; + savedSearchData$: SavedSearchData; + dataView: DataView; + savedSearch: SavedSearch; + isTimeBased: boolean; + isPlainRecord: boolean; +}) => { + const { storage, data } = useDiscoverServices(); + + /** + * Visualize + */ + + const timeField = dataView.timeFieldName && dataView.getFieldByName(dataView.timeFieldName); + const [canVisualize, setCanVisualize] = useState(false); + + useEffect(() => { + if (!timeField) { + return; + } + getVisualizeInformation( + getUiActions(), + timeField, + dataView, + savedSearch.columns || [], + [] + ).then((info) => { + setCanVisualize(Boolean(info)); + }); + }, [dataView, savedSearch.columns, timeField]); + + const onEditVisualization = useCallback(() => { + if (!timeField) { + return; + } + triggerVisualizeActions( + getUiActions(), + timeField, + savedSearch.columns || [], + PLUGIN_ID, + dataView + ); + }, [dataView, savedSearch.columns, timeField]); + + /** + * Height + */ + + const [topPanelHeight, setTopPanelHeight] = useState(() => { + const storedHeight = storage.get(HISTOGRAM_HEIGHT_KEY); + return storedHeight ? Number(storedHeight) : undefined; + }); + + const onTopPanelHeightChange = useCallback( + (newTopPanelHeight: number | undefined) => { + storage.set(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + setTopPanelHeight(newTopPanelHeight); + }, + [storage] + ); + + /** + * Other callbacks + */ + + const onChartHiddenChange = useCallback( + (chartHidden: boolean) => { + storage.set(CHART_HIDDEN_KEY, chartHidden); + stateContainer.setAppState({ hideChart: chartHidden }); + }, + [stateContainer, storage] + ); + + const onTimeIntervalChange = useCallback( + (newInterval: string) => { + stateContainer.setAppState({ interval: newInterval }); + }, + [stateContainer] + ); + + /** + * Data + */ + + const { fetchStatus: hitsFetchStatus, result: hitsTotal } = useDataState( + savedSearchData$.totalHits$ + ); + + const hits = useMemo( + () => + isPlainRecord + ? undefined + : { + status: hitsFetchStatus, + total: hitsTotal, + }, + [hitsFetchStatus, hitsTotal, isPlainRecord] + ); + + const { fetchStatus: chartFetchStatus, response, error } = useDataState(savedSearchData$.charts$); + + const { bucketInterval, chartData } = useMemo( + () => + buildChartData({ + data, + dataView, + timeInterval: state.interval, + response, + }), + [data, dataView, response, state.interval] + ); + + const chart = useMemo( + () => + isPlainRecord || !isTimeBased + ? undefined + : { + status: chartFetchStatus, + hidden: state.hideChart, + timeInterval: state.interval, + bucketInterval, + data: chartData, + error, + }, + [ + bucketInterval, + chartData, + chartFetchStatus, + error, + isPlainRecord, + isTimeBased, + state.hideChart, + state.interval, + ] + ); + + return { + topPanelHeight, + hits, + chart, + onEditVisualization: canVisualize ? onEditVisualization : undefined, + onTopPanelHeightChange, + onChartHiddenChange, + onTimeIntervalChange, + }; +}; diff --git a/src/plugins/discover/public/application/main/hooks/use_data_state.ts b/src/plugins/discover/public/application/main/hooks/use_data_state.ts index 7bfa4205081e9..fe512e747b4a1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_data_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_data_state.ts @@ -9,8 +9,8 @@ import { useState, useEffect } from 'react'; import { BehaviorSubject } from 'rxjs'; import { DataMsg } from './use_saved_search'; -export function useDataState(data$: BehaviorSubject) { - const [fetchState, setFetchState] = useState(data$.getValue()); +export function useDataState(data$: BehaviorSubject) { + const [fetchState, setFetchState] = useState(data$.getValue()); useEffect(() => { const subscription = data$.subscribe((next) => { diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts index 4762748e2618b..2f097daac982d 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts @@ -12,12 +12,12 @@ import { ISearchSource } from '@kbn/data-plugin/public'; import { RequestAdapter } from '@kbn/inspector-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { AggregateQuery, Query } from '@kbn/es-query'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { getRawRecordType } from '../utils/get_raw_record_type'; import { DiscoverServices } from '../../../build_services'; import { DiscoverSearchSessionManager } from '../services/discover_search_session'; import { GetStateReturn } from '../services/discover_state'; import { validateTimeRange } from '../utils/validate_time_range'; -import { Chart } from '../components/chart/point_series'; import { useSingleton } from './use_singleton'; import { FetchStatus } from '../../types'; import { fetchAll } from '../utils/fetch_all'; @@ -34,12 +34,6 @@ export interface SavedSearchData { availableFields$: AvailableFields$; } -export interface TimechartBucketInterval { - scaled?: boolean; - description?: string; - scale?: number; -} - export type DataMain$ = BehaviorSubject; export type DataDocuments$ = BehaviorSubject; export type DataTotalHits$ = BehaviorSubject; @@ -90,8 +84,7 @@ export interface DataTotalHitsMsg extends DataMsg { } export interface DataChartsMessage extends DataMsg { - bucketInterval?: TimechartBucketInterval; - chartData?: Chart; + response?: SearchResponse; } export interface DataAvailableFieldsMsg extends DataMsg { diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts index 0d6caf180a3f6..ae5abb36378a8 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts @@ -107,8 +107,7 @@ export function sendResetMsg(data: SavedSearchData, initialFetchStatus: FetchSta }); data.charts$.next({ fetchStatus: initialFetchStatus, - chartData: undefined, - bucketInterval: undefined, + response: undefined, recordRawType, }); data.totalHits$.next({ diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 288595fa5f7a5..59dbc3ffe73d8 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -30,6 +30,7 @@ import { fetchChart } from './fetch_chart'; import { fetchTotalHits } from './fetch_total_hits'; import { buildDataTableRecord } from '../../../utils/build_data_record'; import { dataViewMock } from '../../../__mocks__/data_view'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; jest.mock('./fetch_documents', () => ({ fetchDocuments: jest.fn().mockResolvedValue([]), @@ -99,8 +100,7 @@ describe('test fetchAll', () => { mockFetchTotalHits.mockReset().mockResolvedValue(42); mockFetchChart .mockReset() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - .mockResolvedValue({ totalHits: 42, chartData: {} as any, bucketInterval: {} }); + .mockResolvedValue({ totalHits: 42, response: {} as unknown as SearchResponse }); }); test('changes of fetchStatus when starting with FetchStatus.UNINITIALIZED', async () => { @@ -157,7 +157,7 @@ describe('test fetchAll', () => { ]); }); - test('emits loading and chartData on charts$ correctly', async () => { + test('emits loading and response on charts$ correctly', async () => { const collect = subjectCollector(subjects.charts$); searchSource.getField('index')!.isTimeBased = () => true; await fetchAll(subjects, searchSource, false, deps); @@ -167,8 +167,7 @@ describe('test fetchAll', () => { { fetchStatus: FetchStatus.COMPLETE, recordRawType: 'document', - bucketInterval: {}, - chartData: {}, + response: {}, }, ]); }); @@ -176,8 +175,7 @@ describe('test fetchAll', () => { test('should use charts query to fetch total hit count when chart is visible', async () => { const collect = subjectCollector(subjects.totalHits$); searchSource.getField('index')!.isTimeBased = () => true; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mockFetchChart.mockResolvedValue({ bucketInterval: {}, chartData: {} as any, totalHits: 32 }); + mockFetchChart.mockResolvedValue({ totalHits: 32, response: {} as unknown as SearchResponse }); await fetchAll(subjects, searchSource, false, deps); expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index 853ae6cebfb76..d530da1492fac 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -172,8 +172,7 @@ export function fetchAll( dataSubjects.charts$.next({ fetchStatus: FetchStatus.COMPLETE, - chartData: chart.chartData, - bucketInterval: chart.bucketInterval, + response: chart.response, recordRawType, }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts index d2e23dc227564..e1020404d3996 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts @@ -107,8 +107,7 @@ describe('test fetchCharts', () => { const result = await fetchChart(savedSearchMockWithTimeField.searchSource, getDeps()); expect(result).toHaveProperty('totalHits', 42); - expect(result).toHaveProperty('bucketInterval.description', '0 milliseconds'); - expect(result).toHaveProperty('chartData'); + expect(result).toHaveProperty('response'); }); test('rejects promise on query failure', async () => { diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.ts index 66cd66f1418d8..e4e5b67782cb9 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_chart.ts @@ -5,33 +5,27 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + import { i18n } from '@kbn/i18n'; import { filter, map } from 'rxjs/operators'; import { lastValueFrom } from 'rxjs'; -import { - DataPublicPluginStart, - isCompleteResponse, - search, - ISearchSource, - tabifyAggResponse, -} from '@kbn/data-plugin/public'; -import { getChartAggConfigs, getDimensions } from '.'; -import { buildPointSeriesData, Chart } from '../components/chart/point_series'; -import { TimechartBucketInterval } from '../hooks/use_saved_search'; +import { DataPublicPluginStart, isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { getChartAggConfigs } from '@kbn/unified-histogram-plugin/public'; import { FetchDeps } from './fetch_all'; interface Result { totalHits: number; - chartData: Chart; - bucketInterval: TimechartBucketInterval | undefined; + response: SearchResponse; } export function fetchChart( searchSource: ISearchSource, { abortController, appStateContainer, data, inspectorAdapters, searchSessionId }: FetchDeps ): Promise { - const interval = appStateContainer.getState().interval ?? 'auto'; - const chartAggConfigs = updateSearchSource(searchSource, interval, data); + const timeInterval = appStateContainer.getState().interval ?? 'auto'; + + updateSearchSource(searchSource, timeInterval, data); const executionContext = { description: 'fetch chart data and total hits', @@ -55,20 +49,10 @@ export function fetchChart( }) .pipe( filter((res) => isCompleteResponse(res)), - map((res) => { - const bucketAggConfig = chartAggConfigs.aggs[1]; - const tabifiedData = tabifyAggResponse(chartAggConfigs, res.rawResponse); - const dimensions = getDimensions(chartAggConfigs, data); - const bucketInterval = search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) - ? bucketAggConfig?.buckets?.getInterval() - : undefined; - const chartData = buildPointSeriesData(tabifiedData, dimensions!); - return { - chartData, - bucketInterval, - totalHits: res.rawResponse.hits.total as number, - }; - }) + map((res) => ({ + response: res.rawResponse, + totalHits: res.rawResponse.hits.total as number, + })) ); return lastValueFrom(fetch$); @@ -76,14 +60,14 @@ export function fetchChart( export function updateSearchSource( searchSource: ISearchSource, - interval: string, + timeInterval: string, data: DataPublicPluginStart ) { const dataView = searchSource.getField('index')!; searchSource.setField('filter', data.query.timefilter.timefilter.createFilter(dataView)); searchSource.setField('size', 0); searchSource.setField('trackTotalHits', true); - const chartAggConfigs = getChartAggConfigs(searchSource, interval, data); + const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); searchSource.setField('aggs', chartAggConfigs.toDsl()); searchSource.removeField('sort'); searchSource.removeField('fields'); diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts index a4a43fa342715..b8b3c3579f343 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts @@ -19,7 +19,7 @@ import { } from '../../../../common'; import { AppState } from '../services/discover_state'; -import { CHART_HIDDEN_KEY } from '../components/chart/discover_chart'; +import { CHART_HIDDEN_KEY } from '../components/layout/use_discover_histogram'; function getDefaultColumns(savedSearch: SavedSearch, uiSettings: IUiSettingsClient) { if (savedSearch.columns && savedSearch.columns.length > 0) { diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index 27cfcb9079f21..93488793f8237 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -33,6 +33,7 @@ { "path": "../../../x-pack/plugins/spaces/tsconfig.json" }, { "path": "../data_view_editor/tsconfig.json" }, { "path": "../../../x-pack/plugins/triggers_actions_ui/tsconfig.json" }, - { "path": "../saved_objects_tagging_oss/tsconfig.json" } + { "path": "../saved_objects_tagging_oss/tsconfig.json" }, + { "path": "../unified_histogram/tsconfig.json" } ] } diff --git a/src/plugins/embeddable/common/types.ts b/src/plugins/embeddable/common/types.ts index c37b3ee2b720c..fd4a94419613a 100644 --- a/src/plugins/embeddable/common/types.ts +++ b/src/plugins/embeddable/common/types.ts @@ -58,6 +58,11 @@ export type EmbeddableInput = { */ syncColors?: boolean; + /** + * Flag whether cursor should be synced with other panels on hover + */ + syncCursor?: boolean; + /** * Flag whether tooltips should be synced with other panels on hover */ diff --git a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts index 1dfd056bc75c0..41a68fc0f2444 100644 --- a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts +++ b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.test.ts @@ -21,6 +21,7 @@ const getGenericEmbeddableState = (state?: Partial): Embeddable enhancements: undefined, syncColors: false, syncTooltips: false, + syncCursor: true, viewMode: ViewMode.VIEW, title: 'So Very Generic', id: 'soVeryGeneric', @@ -46,6 +47,7 @@ test('Omitting generic embeddable input omits all generic input keys', () => { 'enhancements', 'syncColors', 'syncTooltips', + 'syncCursor', 'viewMode', 'title', 'id', diff --git a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.ts b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.ts index a66294d08bdc4..8602e174205d7 100644 --- a/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.ts +++ b/src/plugins/embeddable/public/lib/embeddables/diff_embeddable_input.ts @@ -20,6 +20,7 @@ const allGenericInputKeys: Readonly> = [ 'disableTriggers', 'enhancements', 'syncColors', + 'syncCursor', 'syncTooltips', 'viewMode', 'title', @@ -32,6 +33,7 @@ const genericInputKeysToCompare = [ 'disableTriggers', 'enhancements', 'syncColors', + 'syncCursor', 'syncTooltips', 'title', 'id', diff --git a/src/plugins/embeddable/public/store/input_slice.ts b/src/plugins/embeddable/public/store/input_slice.ts index da4bc6618ae11..48c9ccb98b6ba 100644 --- a/src/plugins/embeddable/public/store/input_slice.ts +++ b/src/plugins/embeddable/public/store/input_slice.ts @@ -40,6 +40,9 @@ export const input = createSlice({ setSyncColors(state, action: PayloadAction) { state.syncColors = action.payload; }, + setSyncCursor(state, action: PayloadAction) { + state.syncCursor = action.payload; + }, setSyncTooltips(state, action: PayloadAction) { state.syncTooltips = action.payload; }, diff --git a/src/plugins/expressions/common/execution/execution.ts b/src/plugins/expressions/common/execution/execution.ts index 68cebaa65569b..30016f36d77d6 100644 --- a/src/plugins/expressions/common/execution/execution.ts +++ b/src/plugins/expressions/common/execution/execution.ts @@ -225,6 +225,7 @@ export class Execution< inspectorAdapters.tables[name] = datatable; }, isSyncColorsEnabled: () => execution.params.syncColors!, + isSyncCursorEnabled: () => execution.params.syncCursor!, isSyncTooltipsEnabled: () => execution.params.syncTooltips!, ...execution.executor.context, getExecutionContext: () => execution.params.executionContext, diff --git a/src/plugins/expressions/common/execution/types.ts b/src/plugins/expressions/common/execution/types.ts index debe34e223e08..dddc503285942 100644 --- a/src/plugins/expressions/common/execution/types.ts +++ b/src/plugins/expressions/common/execution/types.ts @@ -65,6 +65,11 @@ export interface ExecutionContext< */ isSyncColorsEnabled?: () => boolean; + /** + * Returns the state (true|false) of the sync cursor across panels switch. + */ + isSyncCursorEnabled?: () => boolean; + /** * Returns the state (true|false) of the sync tooltips across panels switch. */ diff --git a/src/plugins/expressions/common/expression_renderers/types.ts b/src/plugins/expressions/common/expression_renderers/types.ts index 04c3c48cc383c..8f5fc21e205c7 100644 --- a/src/plugins/expressions/common/expression_renderers/types.ts +++ b/src/plugins/expressions/common/expression_renderers/types.ts @@ -93,6 +93,8 @@ export interface IInterpreterRenderHandlers { isSyncColorsEnabled(): boolean; + isSyncCursorEnabled(): boolean; + isSyncTooltipsEnabled(): boolean; /** * This uiState interface is actually `PersistedState` from the visualizations plugin, diff --git a/src/plugins/expressions/common/service/expressions_services.ts b/src/plugins/expressions/common/service/expressions_services.ts index 530bce8066716..097b0823a98f0 100644 --- a/src/plugins/expressions/common/service/expressions_services.ts +++ b/src/plugins/expressions/common/service/expressions_services.ts @@ -152,6 +152,8 @@ export interface ExpressionExecutionParams { syncColors?: boolean; + syncCursor?: boolean; + syncTooltips?: boolean; inspectorAdapters?: Adapters; diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index c8b0cf6845b86..5b1ae822e1a2c 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -114,6 +114,7 @@ export class ExpressionLoader { renderMode: params?.renderMode, syncColors: params?.syncColors, syncTooltips: params?.syncTooltips, + syncCursor: params?.syncCursor, hasCompatibleActions: params?.hasCompatibleActions, executionContext: params?.executionContext, }); @@ -199,6 +200,7 @@ export class ExpressionLoader { searchSessionId: params.searchSessionId, debug: params.debug, syncColors: params.syncColors, + syncCursor: params?.syncCursor, syncTooltips: params.syncTooltips, executionContext: params.executionContext, }); @@ -238,6 +240,7 @@ export class ExpressionLoader { this.params.searchSessionId = params.searchSessionId; } this.params.syncColors = params.syncColors; + this.params.syncCursor = params.syncCursor; this.params.syncTooltips = params.syncTooltips; this.params.debug = Boolean(params.debug); this.params.partial = Boolean(params.partial); diff --git a/src/plugins/expressions/public/react_expression_renderer/use_expression_renderer.ts b/src/plugins/expressions/public/react_expression_renderer/use_expression_renderer.ts index bb2c716313a1c..865a3ef21fb6f 100644 --- a/src/plugins/expressions/public/react_expression_renderer/use_expression_renderer.ts +++ b/src/plugins/expressions/public/react_expression_renderer/use_expression_renderer.ts @@ -116,6 +116,7 @@ export function useExpressionRenderer( debouncedLoaderParams.renderMode, debouncedLoaderParams.syncColors, debouncedLoaderParams.syncTooltips, + debouncedLoaderParams.syncCursor, ]); useEffect(() => { diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index 048f73ef66fa5..fd550b2888316 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -30,6 +30,7 @@ export interface ExpressionRenderHandlerParams { onRenderError?: RenderErrorHandlerFnType; renderMode?: RenderMode; syncColors?: boolean; + syncCursor?: boolean; syncTooltips?: boolean; interactive?: boolean; hasCompatibleActions?: (event: ExpressionRendererEvent) => Promise; @@ -59,6 +60,7 @@ export class ExpressionRenderHandler { renderMode, syncColors, syncTooltips, + syncCursor, interactive, hasCompatibleActions = async () => false, executionContext, @@ -106,6 +108,9 @@ export class ExpressionRenderHandler { isSyncTooltipsEnabled: () => { return syncTooltips || false; }, + isSyncCursorEnabled: () => { + return syncCursor || true; + }, isInteractive: () => { return interactive ?? true; }, diff --git a/src/plugins/expressions/public/types/index.ts b/src/plugins/expressions/public/types/index.ts index b035daf4deefc..c47eb4592fa4f 100644 --- a/src/plugins/expressions/public/types/index.ts +++ b/src/plugins/expressions/public/types/index.ts @@ -50,6 +50,7 @@ export interface IExpressionLoaderParams { searchSessionId?: string; renderMode?: RenderMode; syncColors?: boolean; + syncCursor?: boolean; syncTooltips?: boolean; hasCompatibleActions?: ExpressionRenderHandlerParams['hasCompatibleActions']; executionContext?: KibanaExecutionContext; diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts index 379431d676cf6..7da98a954773c 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/rollups/integration_tests/daily_rollups.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { Logger, ISavedObjectsRepository } from '@kbn/core/server'; +import type { Logger, ISavedObjectsRepository, SavedObject } from '@kbn/core/server'; import { createTestServers, TestElasticsearchUtils, @@ -25,7 +25,7 @@ import moment from 'moment'; const eventLoopDelaysMonitor = metricsServiceMock.createEventLoopDelaysMonitor(); -function createRawObject(date: moment.MomentInput) { +function createRawObject(date: moment.MomentInput): SavedObject { const pid = Math.round(Math.random() * 10000); const instanceUuid = 'mock_instance'; @@ -39,26 +39,33 @@ function createRawObject(date: moment.MomentInput) { processId: pid, instanceUuid, }, + references: [], }; } -const rawEventLoopDelaysDaily = [ - createRawObject(moment.now()), - createRawObject(moment.now()), - createRawObject(moment().subtract(1, 'days')), - createRawObject(moment().subtract(3, 'days')), -]; +function createRawEventLoopDelaysDailyDocs() { + const rawEventLoopDelaysDaily = [ + createRawObject(moment.now()), + createRawObject(moment.now()), + createRawObject(moment().subtract(1, 'days')), + createRawObject(moment().subtract(3, 'days')), + ]; -const outdatedRawEventLoopDelaysDaily = [ - createRawObject(moment().subtract(5, 'days')), - createRawObject(moment().subtract(7, 'days')), -]; + const outdatedRawEventLoopDelaysDaily = [ + createRawObject(moment().subtract(5, 'days')), + createRawObject(moment().subtract(7, 'days')), + ]; + + return { rawEventLoopDelaysDaily, outdatedRawEventLoopDelaysDaily }; +} describe(`daily rollups integration test`, () => { let esServer: TestElasticsearchUtils; let root: TestKibanaUtils['root']; let internalRepository: ISavedObjectsRepository; let logger: Logger; + let rawEventLoopDelaysDaily: Array>; + let outdatedRawEventLoopDelaysDaily: Array>; beforeAll(async () => { const { startES } = createTestServers({ @@ -74,6 +81,20 @@ describe(`daily rollups integration test`, () => { logger = root.logger.get('test daily rollups'); internalRepository = start.savedObjects.createInternalRepository([SAVED_OBJECTS_DAILY_TYPE]); + // If we are less than 1 second away from midnight, let's wait 1 second before creating the docs. + // Otherwise, we may receive 1 document less than the expected ones. + if (moment().endOf('day').diff(moment(), 's', true) < 1) { + logger.info( + 'Delaying the creation of the docs 1s, just in case we create them before midnight and run the tests on the following day.' + ); + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + + // Create the docs now + const rawDailyDocs = createRawEventLoopDelaysDailyDocs(); + rawEventLoopDelaysDaily = rawDailyDocs.rawEventLoopDelaysDaily; + outdatedRawEventLoopDelaysDaily = rawDailyDocs.outdatedRawEventLoopDelaysDaily; + await internalRepository.bulkCreate( [...rawEventLoopDelaysDaily, ...outdatedRawEventLoopDelaysDaily], { refresh: true } @@ -90,8 +111,13 @@ describe(`daily rollups integration test`, () => { const { total, saved_objects: savedObjects } = await internalRepository.find({ type: SAVED_OBJECTS_DAILY_TYPE }); expect(total).toBe(rawEventLoopDelaysDaily.length); - expect(savedObjects.map(({ id, type, attributes }) => ({ id, type, attributes }))).toEqual( - rawEventLoopDelaysDaily - ); + expect( + savedObjects.map(({ id, type, attributes, references }) => ({ + id, + type, + attributes, + references, + })) + ).toEqual(rawEventLoopDelaysDaily); }); }); diff --git a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx index 2f07824d884a0..652ff58a5ab4a 100644 --- a/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx +++ b/src/plugins/navigation/public/top_nav_menu/top_nav_menu.tsx @@ -24,7 +24,6 @@ export type TopNavMenuProps = config?: TopNavMenuData[]; badges?: Array; showSearchBar?: boolean; - showQueryBar?: boolean; showQueryInput?: boolean; showDatePicker?: boolean; showFilterBar?: boolean; @@ -142,7 +141,6 @@ export function TopNavMenu( TopNavMenu.defaultProps = { showSearchBar: false, - showQueryBar: true, showQueryInput: true, showDatePicker: true, showFilterBar: true, diff --git a/src/plugins/presentation_util/public/__stories__/render.tsx b/src/plugins/presentation_util/public/__stories__/render.tsx index b96dfcbc0fbe9..ca9f968842270 100644 --- a/src/plugins/presentation_util/public/__stories__/render.tsx +++ b/src/plugins/presentation_util/public/__stories__/render.tsx @@ -16,6 +16,7 @@ import { export const defaultHandlers: IInterpreterRenderHandlers = { getRenderMode: () => 'view', isSyncColorsEnabled: () => false, + isSyncCursorEnabled: () => true, isSyncTooltipsEnabled: () => false, isInteractive: () => true, getExecutionContext: () => undefined, diff --git a/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap b/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap index 3278c01dd86da..b0fed8a7bd3b5 100644 --- a/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap +++ b/src/plugins/share/public/components/__snapshots__/url_panel_content.test.tsx.snap @@ -42,38 +42,40 @@ exports[`share url panel content render 1`] = ` Object { "data-test-subj": "exportAsSnapshot", "id": "snapshot", - "label": - - - - + - + + + + - } - position="bottom" - /> - - , + /> + } + position="bottom" + /> + + + , }, Object { "data-test-subj": "exportAsSavedObject", @@ -225,38 +227,40 @@ exports[`share url panel content should enable saved object export option when o Object { "data-test-subj": "exportAsSnapshot", "id": "snapshot", - "label": - - - - + - + + + + - } - position="bottom" - /> - - , + /> + } + position="bottom" + /> + + + , }, Object { "data-test-subj": "exportAsSavedObject", @@ -408,38 +412,40 @@ exports[`share url panel content should hide short url section when allowShortUr Object { "data-test-subj": "exportAsSnapshot", "id": "snapshot", - "label": - - - - + - + + + + - } - position="bottom" - /> - - , + /> + } + position="bottom" + /> + + + , }, Object { "data-test-subj": "exportAsSavedObject", @@ -527,38 +533,40 @@ exports[`should show url param extensions 1`] = ` Object { "data-test-subj": "exportAsSnapshot", "id": "snapshot", - "label": - - - - + - + + + + - } - position="bottom" - /> - - , + /> + } + position="bottom" + /> + + + , }, Object { "data-test-subj": "exportAsSavedObject", diff --git a/src/plugins/share/public/components/share_context_menu.tsx b/src/plugins/share/public/components/share_context_menu.tsx index 3550711ac84c3..c964737026b3b 100644 --- a/src/plugins/share/public/components/share_context_menu.tsx +++ b/src/plugins/share/public/components/share_context_menu.tsx @@ -32,6 +32,7 @@ export interface ShareContextMenuProps { anonymousAccess?: AnonymousAccessServiceContract; showPublicUrlSwitch?: (anonymousUserCapabilities: Capabilities) => boolean; urlService: BrowserUrlService; + snapshotShareWarning?: string; } export class ShareContextMenu extends Component { @@ -66,6 +67,7 @@ export class ShareContextMenu extends Component { anonymousAccess={this.props.anonymousAccess} showPublicUrlSwitch={this.props.showPublicUrlSwitch} urlService={this.props.urlService} + snapshotShareWarning={this.props.snapshotShareWarning} /> ), }; @@ -96,6 +98,7 @@ export class ShareContextMenu extends Component { anonymousAccess={this.props.anonymousAccess} showPublicUrlSwitch={this.props.showPublicUrlSwitch} urlService={this.props.urlService} + snapshotShareWarning={this.props.snapshotShareWarning} /> ), }; diff --git a/src/plugins/share/public/components/url_panel_content.tsx b/src/plugins/share/public/components/url_panel_content.tsx index 54d3c8aa7e7ec..32441ab2945eb 100644 --- a/src/plugins/share/public/components/url_panel_content.tsx +++ b/src/plugins/share/public/components/url_panel_content.tsx @@ -20,6 +20,7 @@ import { EuiRadioGroup, EuiSwitch, EuiSwitchEvent, + EuiToolTip, } from '@elastic/eui'; import { format as formatUrl, parse as parseUrl } from 'url'; @@ -45,6 +46,7 @@ export interface UrlPanelContentProps { anonymousAccess?: AnonymousAccessServiceContract; showPublicUrlSwitch?: (anonymousUserCapabilities: Capabilities) => boolean; urlService: BrowserUrlService; + snapshotShareWarning?: string; } export enum ExportUrlAsType { @@ -78,7 +80,6 @@ export class UrlPanelContent extends Component { super(props); this.shortUrlCache = undefined; - this.state = { exportUrlAs: ExportUrlAsType.EXPORT_URL_AS_SNAPSHOT, useShortUrl: false, @@ -155,6 +156,33 @@ export class UrlPanelContent extends Component { ); + const showWarningButton = + this.props.snapshotShareWarning && + this.state.exportUrlAs === ExportUrlAsType.EXPORT_URL_AS_SNAPSHOT; + + const copyButton = (copy: () => void) => ( + + {this.props.isEmbedded ? ( + + ) : ( + + )} + + ); + return ( @@ -166,27 +194,19 @@ export class UrlPanelContent extends Component { {(copy: () => void) => ( - - {this.props.isEmbedded ? ( - + <> + {showWarningButton ? ( + + {copyButton(copy)} + ) : ( - + copyButton(copy) )} - + )} @@ -246,13 +266,11 @@ export class UrlPanelContent extends Component { }, }), }); - return this.updateUrlParams(formattedUrl); }; private getSnapshotUrl = () => { const url = this.props.shareableUrl || window.location.href; - return this.updateUrlParams(url); }; @@ -404,17 +422,24 @@ export class UrlPanelContent extends Component { }; private renderExportUrlAsOptions = () => { + const snapshotLabel = ( + + ); return [ { id: ExportUrlAsType.EXPORT_URL_AS_SNAPSHOT, - label: this.renderWithIconTip( - , - + values={{ objectType: this.props.objectType }} + /> + )} + ), ['data-test-subj']: 'exportAsSnapshot', }, diff --git a/src/plugins/share/public/services/share_menu_manager.tsx b/src/plugins/share/public/services/share_menu_manager.tsx index 6f27fc8030969..a393d4aba6033 100644 --- a/src/plugins/share/public/services/share_menu_manager.tsx +++ b/src/plugins/share/public/services/share_menu_manager.tsx @@ -74,6 +74,7 @@ export class ShareMenuManager { showPublicUrlSwitch, urlService, anonymousAccess, + snapshotShareWarning, onClose, }: ShowShareMenuOptions & { menuItems: ShareMenuItem[]; @@ -114,6 +115,7 @@ export class ShareMenuManager { anonymousAccess={anonymousAccess} showPublicUrlSwitch={showPublicUrlSwitch} urlService={urlService} + snapshotShareWarning={snapshotShareWarning} /> diff --git a/src/plugins/share/public/types.ts b/src/plugins/share/public/types.ts index 355b890c9028c..b1cd995a5ff84 100644 --- a/src/plugins/share/public/types.ts +++ b/src/plugins/share/public/types.ts @@ -97,5 +97,6 @@ export interface ShowShareMenuOptions extends Omit { allowEmbed: boolean; allowShortUrl: boolean; embedUrlParamExtensions?: UrlParamExtension[]; + snapshotShareWarning?: string; onClose?: () => void; } diff --git a/src/plugins/unified_histogram/README.md b/src/plugins/unified_histogram/README.md new file mode 100755 index 0000000000000..301216dfefdbf --- /dev/null +++ b/src/plugins/unified_histogram/README.md @@ -0,0 +1,3 @@ +# unifiedHistogram + +The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. diff --git a/src/plugins/unified_histogram/jest.config.js b/src/plugins/unified_histogram/jest.config.js new file mode 100644 index 0000000000000..3b8213b533691 --- /dev/null +++ b/src/plugins/unified_histogram/jest.config.js @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/src/plugins/unified_histogram'], + coverageDirectory: '/target/kibana-coverage/jest/src/plugins/unified_histogram', + coverageReporters: ['text', 'html'], + collectCoverageFrom: [ + '/src/plugins/unified_histogram/{common,public,server}/**/*.{ts,tsx}', + ], +}; diff --git a/src/plugins/unified_histogram/kibana.json b/src/plugins/unified_histogram/kibana.json new file mode 100755 index 0000000000000..f89f9c9d4c714 --- /dev/null +++ b/src/plugins/unified_histogram/kibana.json @@ -0,0 +1,15 @@ +{ + "id": "unifiedHistogram", + "version": "1.0.0", + "kibanaVersion": "kibana", + "owner": { + "name": "Data Discovery", + "githubTeam": "kibana-data-discovery" + }, + "description": "The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display.", + "server": false, + "ui": true, + "requiredPlugins": [], + "optionalPlugins": [], + "requiredBundles": ["charts", "data"] +} diff --git a/src/plugins/unified_histogram/public/__mocks__/data_view.ts b/src/plugins/unified_histogram/public/__mocks__/data_view.ts new file mode 100644 index 0000000000000..e51b9560949ab --- /dev/null +++ b/src/plugins/unified_histogram/public/__mocks__/data_view.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView } from '@kbn/data-views-plugin/public'; + +const fields = [ + { + name: '_source', + type: '_source', + scripted: false, + filterable: false, + aggregatable: false, + }, + { + name: '_index', + type: 'string', + scripted: false, + filterable: true, + aggregatable: false, + }, + { + name: 'message', + type: 'string', + displayName: 'message', + scripted: false, + filterable: false, + aggregatable: false, + }, + { + name: 'extension', + type: 'string', + displayName: 'extension', + scripted: false, + filterable: true, + aggregatable: true, + }, + { + name: 'bytes', + type: 'number', + displayName: 'bytesDisplayName', + scripted: false, + filterable: true, + aggregatable: true, + sortable: true, + }, + { + name: 'scripted', + type: 'number', + displayName: 'scripted', + scripted: true, + filterable: false, + }, + { + name: 'object.value', + type: 'number', + displayName: 'object.value', + scripted: false, + filterable: true, + aggregatable: true, + }, +] as DataView['fields']; + +export const buildDataViewMock = ({ + name, + fields: definedFields, + timeFieldName, +}: { + name: string; + fields: DataView['fields']; + timeFieldName?: string; +}): DataView => { + const dataViewFields = [...definedFields] as DataView['fields']; + + dataViewFields.getByName = (fieldName: string) => { + return dataViewFields.find((field) => field.name === fieldName); + }; + + dataViewFields.getAll = () => { + return dataViewFields; + }; + + const dataView = { + id: `${name}-id`, + title: `${name}-title`, + name, + metaFields: ['_index', '_score'], + fields: dataViewFields, + getName: () => name, + getComputedFields: () => ({ docvalueFields: [], scriptFields: {}, storedFields: ['*'] }), + getSourceFiltering: () => ({}), + getFieldByName: jest.fn((fieldName: string) => dataViewFields.getByName(fieldName)), + timeFieldName: timeFieldName || '', + docvalueFields: [], + getFormatterForField: jest.fn(() => ({ convert: (value: unknown) => value })), + isTimeNanosBased: () => false, + isPersisted: () => true, + } as unknown as DataView; + + dataView.isTimeBased = () => !!timeFieldName; + + return dataView; +}; + +export const dataViewMock = buildDataViewMock({ name: 'the-data-view', fields }); diff --git a/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts new file mode 100644 index 0000000000000..158d697d67c71 --- /dev/null +++ b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView } from '@kbn/data-views-plugin/public'; +import { buildDataViewMock } from './data_view'; + +const fields = [ + { + name: '_index', + type: 'string', + scripted: false, + filterable: true, + }, + { + name: 'timestamp', + type: 'date', + scripted: false, + filterable: true, + aggregatable: true, + sortable: true, + }, + { + name: 'message', + type: 'string', + scripted: false, + filterable: false, + }, + { + name: 'extension', + type: 'string', + scripted: false, + filterable: true, + aggregatable: true, + }, + { + name: 'bytes', + type: 'number', + scripted: false, + filterable: true, + aggregatable: true, + }, + { + name: 'scripted', + type: 'number', + scripted: true, + filterable: false, + }, +] as DataView['fields']; + +export const dataViewWithTimefieldMock = buildDataViewMock({ + name: 'index-pattern-with-timefield', + fields, + timeFieldName: 'timestamp', +}); diff --git a/src/plugins/unified_histogram/public/__mocks__/services.ts b/src/plugins/unified_histogram/public/__mocks__/services.ts new file mode 100644 index 0000000000000..e827596d88feb --- /dev/null +++ b/src/plugins/unified_histogram/public/__mocks__/services.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import type { UnifiedHistogramServices } from '../types'; + +const dataPlugin = dataPluginMock.createStartContract(); +dataPlugin.query.filterManager.getFilters = jest.fn(() => []); + +export const unifiedHistogramServicesMock = { + data: dataPlugin, + fieldFormats: fieldFormatsMock, + uiSettings: { + get: jest.fn(), + isDefault: jest.fn(() => true), + }, + theme: { + useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), + useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), + }, +} as unknown as UnifiedHistogramServices; diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts b/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts new file mode 100644 index 0000000000000..6c920a4a1a5ab --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { calculateBounds } from '@kbn/data-plugin/public'; +import { buildChartData } from './build_chart_data'; + +describe('buildChartData', () => { + const getOptions = () => { + const response = { + took: 0, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: 29, + max_score: null, + hits: [], + }, + aggregations: { + '2': { + buckets: [ + { + key_as_string: '2022-10-05T16:00:00.000-03:00', + key: 1664996400000, + doc_count: 6, + }, + { + key_as_string: '2022-10-05T16:30:00.000-03:00', + key: 1664998200000, + doc_count: 2, + }, + { + key_as_string: '2022-10-05T17:00:00.000-03:00', + key: 1665000000000, + doc_count: 3, + }, + { + key_as_string: '2022-10-05T17:30:00.000-03:00', + key: 1665001800000, + doc_count: 8, + }, + { + key_as_string: '2022-10-05T18:00:00.000-03:00', + key: 1665003600000, + doc_count: 10, + }, + ], + }, + }, + }; + const dataView = dataViewWithTimefieldMock; + const dataMock = dataPluginMock.createStartContract(); + dataMock.query.timefilter.timefilter.getTime = () => { + return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; + }; + dataMock.query.timefilter.timefilter.calculateBounds = (timeRange) => { + return calculateBounds(timeRange); + }; + return { + data: dataMock, + dataView, + timeInterval: 'auto', + response, + }; + }; + + const expectedChartData = { + xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], + xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, + xAxisLabel: 'timestamp per 0 milliseconds', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: 'P0D', + intervalESUnit: 'ms', + intervalESValue: 0, + min: '1991-03-29T08:04:00.694Z', + max: '2021-03-29T07:04:00.695Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1664996400000, y: 6 }, + { x: 1664998200000, y: 2 }, + { x: 1665000000000, y: 3 }, + { x: 1665001800000, y: 8 }, + { x: 1665003600000, y: 10 }, + ], + }; + + it('should return the correct data', () => { + const { bucketInterval, chartData } = buildChartData(getOptions()); + expect(bucketInterval!.toString()).toEqual('P0D'); + expect(JSON.stringify(chartData)).toEqual(JSON.stringify(expectedChartData)); + }); + + it('should return an empty object if response or timeInterval is undefined', () => { + expect( + buildChartData({ + ...getOptions(), + response: undefined, + timeInterval: undefined, + }) + ).toEqual({}); + expect( + buildChartData({ + ...getOptions(), + response: undefined, + }) + ).toEqual({}); + expect( + buildChartData({ + ...getOptions(), + timeInterval: undefined, + }) + ).toEqual({}); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.ts b/src/plugins/unified_histogram/public/chart/build_chart_data.ts new file mode 100644 index 0000000000000..03b208802ac4d --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/build_chart_data.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { DataPublicPluginStart, search, tabifyAggResponse } from '@kbn/data-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { UnifiedHistogramBucketInterval } from '../types'; +import { buildPointSeriesData } from './build_point_series_data'; +import { getChartAggConfigs } from './get_chart_agg_configs'; +import { getDimensions } from './get_dimensions'; + +/** + * Convert the response from the chart request into a format that can be used + * by the unified histogram chart. The returned object should be used to update + * {@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}. + */ +export const buildChartData = ({ + data, + dataView, + timeInterval, + response, +}: { + data: DataPublicPluginStart; + dataView: DataView; + timeInterval?: string; + response?: SearchResponse; +}) => { + if (!timeInterval || !response) { + return {}; + } + + const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); + const bucketAggConfig = chartAggConfigs.aggs[1]; + const tabifiedData = tabifyAggResponse(chartAggConfigs, response); + const dimensions = getDimensions(chartAggConfigs, data); + const bucketInterval = search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) + ? (bucketAggConfig?.buckets?.getInterval() as UnifiedHistogramBucketInterval) + : undefined; + const chartData = buildPointSeriesData(tabifiedData, dimensions!); + + return { + bucketInterval, + chartData, + }; +}; diff --git a/src/plugins/discover/public/application/main/components/chart/point_series.test.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts similarity index 96% rename from src/plugins/discover/public/application/main/components/chart/point_series.test.ts rename to src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts index e351daa1930f8..3a7f81aa4cd40 100644 --- a/src/plugins/discover/public/application/main/components/chart/point_series.test.ts +++ b/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import { buildPointSeriesData } from './point_series'; +import { buildPointSeriesData } from './build_point_series_data'; import moment from 'moment'; -import { Unit } from '@kbn/datemath'; +import type { Unit } from '@kbn/datemath'; describe('buildPointSeriesData', () => { test('with valid data', () => { diff --git a/src/plugins/unified_histogram/public/chart/build_point_series_data.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.ts new file mode 100644 index 0000000000000..dc9d97fd0708f --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/build_point_series_data.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { uniq } from 'lodash'; +import type { UnifiedHistogramChartData, Dimensions, Table } from '../types'; + +export const buildPointSeriesData = ( + table: Table, + dimensions: Dimensions +): UnifiedHistogramChartData => { + const { x, y } = dimensions; + const xAccessor = table.columns[x.accessor].id; + const yAccessor = table.columns[y.accessor].id; + const chart = {} as UnifiedHistogramChartData; + + chart.xAxisOrderedValues = uniq(table.rows.map((r) => r[xAccessor] as number)); + chart.xAxisFormat = x.format; + chart.xAxisLabel = table.columns[x.accessor].name; + chart.yAxisFormat = y.format; + const { intervalESUnit, intervalESValue, interval, bounds } = x.params; + chart.ordered = { + date: true, + interval, + intervalESUnit, + intervalESValue, + min: bounds.min, + max: bounds.max, + }; + + chart.yAxisLabel = table.columns[y.accessor].name; + + chart.values = table.rows + .filter((row) => row && row[yAccessor] !== 'NaN') + .map((row) => ({ + x: row[xAccessor] as number, + y: row[yAccessor] as number, + })); + + return chart; +}; diff --git a/src/plugins/unified_histogram/public/chart/chart.test.tsx b/src/plugins/unified_histogram/public/chart/chart.test.tsx new file mode 100644 index 0000000000000..41de0687acfa6 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/chart.test.tsx @@ -0,0 +1,185 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { ReactElement } from 'react'; +import { act } from 'react-dom/test-utils'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; +import { Chart } from './chart'; +import type { ReactWrapper } from 'enzyme'; +import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { HitsCounter } from '../hits_counter'; + +async function mountComponent({ + noChart, + noHits, + chartHidden = false, + appendHistogram, + onEditVisualization = jest.fn(), +}: { + noChart?: boolean; + noHits?: boolean; + chartHidden?: boolean; + appendHistogram?: ReactElement; + onEditVisualization?: null | (() => void); +} = {}) { + const services = unifiedHistogramServicesMock; + services.data.query.timefilter.timefilter.getAbsoluteTime = () => { + return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; + }; + + const chartData = { + xAxisOrderedValues: [ + 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, + 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, + 1624917600000, 1625004000000, 1625090400000, + ], + xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, + xAxisLabel: 'order_date per day', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: { + asMilliseconds: jest.fn(), + }, + intervalESUnit: 'd', + intervalESValue: 1, + min: '2021-03-18T08:28:56.411Z', + max: '2021-07-01T07:28:56.411Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1623880800000, y: 134 }, + { x: 1623967200000, y: 152 }, + { x: 1624053600000, y: 141 }, + { x: 1624140000000, y: 138 }, + { x: 1624226400000, y: 142 }, + { x: 1624312800000, y: 157 }, + { x: 1624399200000, y: 149 }, + { x: 1624485600000, y: 146 }, + { x: 1624572000000, y: 170 }, + { x: 1624658400000, y: 137 }, + { x: 1624744800000, y: 150 }, + { x: 1624831200000, y: 144 }, + { x: 1624917600000, y: 147 }, + { x: 1625004000000, y: 137 }, + { x: 1625090400000, y: 66 }, + ], + } as unknown as UnifiedHistogramChartData; + + const props = { + services: unifiedHistogramServicesMock, + hits: noHits + ? undefined + : { + status: 'complete' as UnifiedHistogramFetchStatus, + number: 2, + }, + chart: noChart + ? undefined + : { + status: 'complete' as UnifiedHistogramFetchStatus, + hidden: chartHidden, + timeInterval: 'auto', + bucketInterval: { + scaled: true, + description: 'test', + scale: 2, + }, + data: chartData, + }, + appendHistogram, + onEditVisualization: onEditVisualization || undefined, + onResetChartHeight: jest.fn(), + onChartHiddenChange: jest.fn(), + onTimeIntervalChange: jest.fn(), + }; + + let instance: ReactWrapper = {} as ReactWrapper; + await act(async () => { + instance = mountWithIntl(); + // wait for initial async loading to complete + await new Promise((r) => setTimeout(r, 0)); + await instance.update(); + }); + return instance; +} + +describe('Chart', () => { + test('render when chart is undefined', async () => { + const component = await mountComponent({ noChart: true }); + expect( + component.find('[data-test-subj="unifiedHistogramChartOptionsToggle"]').exists() + ).toBeFalsy(); + }); + + test('render when chart is defined and onEditVisualization is undefined', async () => { + const component = await mountComponent({ onEditVisualization: null }); + expect( + component.find('[data-test-subj="unifiedHistogramChartOptionsToggle"]').exists() + ).toBeTruthy(); + expect( + component.find('[data-test-subj="unifiedHistogramEditVisualization"]').exists() + ).toBeFalsy(); + }); + + test('render when chart is defined and onEditVisualization is defined', async () => { + const component = await mountComponent(); + expect( + component.find('[data-test-subj="unifiedHistogramChartOptionsToggle"]').exists() + ).toBeTruthy(); + expect( + component.find('[data-test-subj="unifiedHistogramEditVisualization"]').exists() + ).toBeTruthy(); + }); + + test('render when chart.hidden is true', async () => { + const component = await mountComponent({ chartHidden: true }); + expect( + component.find('[data-test-subj="unifiedHistogramChartOptionsToggle"]').exists() + ).toBeTruthy(); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeFalsy(); + }); + + test('render when chart.hidden is false', async () => { + const component = await mountComponent({ chartHidden: false }); + expect( + component.find('[data-test-subj="unifiedHistogramChartOptionsToggle"]').exists() + ).toBeTruthy(); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeTruthy(); + }); + + test('triggers onEditVisualization on click', async () => { + const fn = jest.fn(); + const component = await mountComponent({ onEditVisualization: fn }); + await act(async () => { + await component + .find('[data-test-subj="unifiedHistogramEditVisualization"]') + .first() + .simulate('click'); + }); + + expect(fn).toHaveBeenCalled(); + }); + + it('should render HitsCounter when hits is defined', async () => { + const component = await mountComponent(); + expect(component.find(HitsCounter).exists()).toBeTruthy(); + }); + + it('should not render HitsCounter when hits is undefined', async () => { + const component = await mountComponent({ noHits: true }); + expect(component.find(HitsCounter).exists()).toBeFalsy(); + }); + + it('should render the element passed to appendHistogram', async () => { + const appendHistogram =
      ; + const component = await mountComponent({ appendHistogram }); + expect(component.find('[data-test-subj="appendHistogram"]').exists()).toBeTruthy(); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx b/src/plugins/unified_histogram/public/chart/chart.tsx similarity index 53% rename from src/plugins/discover/public/application/main/components/chart/discover_chart.tsx rename to src/plugins/unified_histogram/public/chart/chart.tsx index e7cc01fb00eaa..0f6c47f8a532e 100644 --- a/src/plugins/discover/public/application/main/components/chart/discover_chart.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.tsx @@ -5,7 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import React, { memo, ReactElement, useCallback, useEffect, useRef, useState } from 'react'; + +import type { ReactElement } from 'react'; +import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import moment from 'moment'; import { EuiButtonIcon, @@ -14,54 +16,48 @@ import { EuiFlexItem, EuiPopover, EuiToolTip, + useEuiBreakpoint, + useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { DataView } from '@kbn/data-views-plugin/public'; -import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import { - getVisualizeInformation, - triggerVisualizeActions, -} from '@kbn/unified-field-list-plugin/public'; +import { css } from '@emotion/react'; import { HitsCounter } from '../hits_counter'; -import { GetStateReturn } from '../../services/discover_state'; -import { DiscoverHistogram } from './histogram'; -import { DataCharts$, DataTotalHits$ } from '../../hooks/use_saved_search'; +import { Histogram } from './histogram'; import { useChartPanels } from './use_chart_panels'; -import { useDiscoverServices } from '../../../../hooks/use_discover_services'; -import { getUiActions } from '../../../../kibana_services'; -import { PLUGIN_ID } from '../../../../../common'; +import type { + UnifiedHistogramChartContext, + UnifiedHistogramHitsContext, + UnifiedHistogramServices, +} from '../types'; -const DiscoverHistogramMemoized = memo(DiscoverHistogram); -export const CHART_HIDDEN_KEY = 'discover:chartHidden'; +export interface ChartProps { + className?: string; + services: UnifiedHistogramServices; + hits?: UnifiedHistogramHitsContext; + chart?: UnifiedHistogramChartContext; + appendHitsCounter?: ReactElement; + appendHistogram?: ReactElement; + onEditVisualization?: () => void; + onResetChartHeight?: () => void; + onChartHiddenChange?: (chartHidden: boolean) => void; + onTimeIntervalChange?: (timeInterval: string) => void; +} -export function DiscoverChart({ +const HistogramMemoized = memo(Histogram); + +export function Chart({ className, - resetSavedSearch, - savedSearch, - savedSearchDataChart$, - savedSearchDataTotalHits$, - stateContainer, - dataView, - hideChart, - interval, - isTimeBased, + services, + hits, + chart, + appendHitsCounter, appendHistogram, + onEditVisualization, onResetChartHeight, -}: { - className?: string; - resetSavedSearch: () => void; - savedSearch: SavedSearch; - savedSearchDataChart$: DataCharts$; - savedSearchDataTotalHits$: DataTotalHits$; - stateContainer: GetStateReturn; - dataView: DataView; - isTimeBased: boolean; - hideChart?: boolean; - interval?: string; - appendHistogram?: ReactElement; - onResetChartHeight?: () => void; -}) { - const { data, storage } = useDiscoverServices(); + onChartHiddenChange, + onTimeIntervalChange, +}: ChartProps) { + const { data } = services; const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({ @@ -69,35 +65,6 @@ export function DiscoverChart({ moveFocus: false, }); - const timeField = dataView.timeFieldName && dataView.getFieldByName(dataView.timeFieldName); - const [canVisualize, setCanVisualize] = useState(false); - - useEffect(() => { - if (!timeField) return; - getVisualizeInformation( - getUiActions(), - timeField, - dataView, - savedSearch.columns || [], - [] - ).then((info) => { - setCanVisualize(Boolean(info)); - }); - }, [dataView, savedSearch.columns, timeField]); - - const onEditVisualization = useCallback(() => { - if (!timeField) { - return; - } - triggerVisualizeActions( - getUiActions(), - timeField, - savedSearch.columns || [], - PLUGIN_ID, - dataView - ); - }, [dataView, savedSearch.columns, timeField]); - const onShowChartOptions = useCallback(() => { setShowChartOptionsPopover(!showChartOptionsPopover); }, [showChartOptionsPopover]); @@ -110,14 +77,13 @@ export function DiscoverChart({ if (chartRef.current.moveFocus && chartRef.current.element) { chartRef.current.element.focus(); } - }, [hideChart]); + }, [chart?.hidden]); const toggleHideChart = useCallback(() => { - const newHideChart = !hideChart; - chartRef.current.moveFocus = !newHideChart; - storage.set(CHART_HIDDEN_KEY, newHideChart); - stateContainer.setAppState({ hideChart: newHideChart }); - }, [hideChart, stateContainer, storage]); + const chartHidden = !chart?.hidden; + chartRef.current.moveFocus = !chartHidden; + onChartHiddenChange?.(chartHidden); + }, [chart?.hidden, onChartHiddenChange]); const timefilterUpdateHandler = useCallback( (ranges: { from: number; to: number }) => { @@ -129,15 +95,43 @@ export function DiscoverChart({ }, [data] ); + const panels = useChartPanels({ + chart, toggleHideChart, - onChangeInterval: (newInterval) => stateContainer.setAppState({ interval: newInterval }), + onTimeIntervalChange: (timeInterval) => onTimeIntervalChange?.(timeInterval), closePopover: () => setShowChartOptionsPopover(false), onResetChartHeight, - hideChart, - interval, }); + const { euiTheme } = useEuiTheme(); + const resultCountCss = css` + padding: ${euiTheme.size.s}; + min-height: ${euiTheme.base * 3}px; + `; + const resultCountTitleCss = css` + ${useEuiBreakpoint(['xs', 's'])} { + margin-bottom: 0 !important; + } + `; + const resultCountToggleCss = css` + ${useEuiBreakpoint(['xs', 's'])} { + align-items: flex-end; + } + `; + const timechartCss = css` + flex-grow: 1; + display: flex; + flex-direction: column; + position: relative; + + // SASSTODO: the visualizing component should have an option or a modifier + .series > rect { + fill-opacity: 0.5; + stroke-width: 1; + } + `; + return ( - + - + {hits && } - {isTimeBased && ( - + {chart && ( + - {canVisualize && ( + {onEditVisualization && ( @@ -172,8 +163,8 @@ export function DiscoverChart({ size="xs" iconType="lensApp" onClick={onEditVisualization} - data-test-subj="discoverEditVisualization" - aria-label={i18n.translate('discover.editVisualizationButton', { + data-test-subj="unifiedHistogramEditVisualization" + aria-label={i18n.translate('unifiedHistogram.editVisualizationButton', { defaultMessage: 'Edit visualization', })} /> @@ -182,10 +173,10 @@ export function DiscoverChart({ )} @@ -193,8 +184,8 @@ export function DiscoverChart({ size="xs" iconType="gear" onClick={onShowChartOptions} - data-test-subj="discoverChartOptionsToggle" - aria-label={i18n.translate('discover.chartOptionsButton', { + data-test-subj="unifiedHistogramChartOptionsToggle" + aria-label={i18n.translate('unifiedHistogram.chartOptionsButton', { defaultMessage: 'Chart options', })} /> @@ -213,20 +204,20 @@ export function DiscoverChart({ )} - {isTimeBased && !hideChart && ( + {chart && !chart.hidden && (
      (chartRef.current.element = element)} tabIndex={-1} - aria-label={i18n.translate('discover.histogramOfFoundDocumentsAriaLabel', { + aria-label={i18n.translate('unifiedHistogram.histogramOfFoundDocumentsAriaLabel', { defaultMessage: 'Histogram of found documents', })} - className="dscTimechart" + css={timechartCss} > -
      {appendHistogram} diff --git a/src/plugins/discover/public/application/main/utils/get_chart_agg_config.test.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts similarity index 75% rename from src/plugins/discover/public/application/main/utils/get_chart_agg_config.test.ts rename to src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts index 67a7fe5285ffe..3b4f470ba6119 100644 --- a/src/plugins/discover/public/application/main/utils/get_chart_agg_config.test.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts @@ -5,28 +5,16 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { dataViewWithTimefieldMock } from '../../../__mocks__/data_view_with_timefield'; -import { ISearchSource } from '@kbn/data-plugin/public'; + +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { getChartAggConfigs } from './get_chart_agg_configs'; describe('getChartAggConfigs', () => { test('is working', () => { const dataView = dataViewWithTimefieldMock; - const setField = jest.fn(); - const searchSource = { - setField, - getField: (name: string) => { - if (name === 'index') { - return dataView; - } - }, - removeField: jest.fn(), - } as unknown as ISearchSource; - const dataMock = dataPluginMock.createStartContract(); - - const aggsConfig = getChartAggConfigs(searchSource, 'auto', dataMock); + const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); expect(aggsConfig!.aggs).toMatchInlineSnapshot(` Array [ diff --git a/src/plugins/discover/public/application/main/utils/get_chart_agg_configs.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts similarity index 62% rename from src/plugins/discover/public/application/main/utils/get_chart_agg_configs.ts rename to src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts index 035a56fa4be16..93ef7f3dd9188 100644 --- a/src/plugins/discover/public/application/main/utils/get_chart_agg_configs.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts @@ -5,18 +5,22 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { DataPublicPluginStart, ISearchSource } from '@kbn/data-plugin/public'; + +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/common'; /** - * Helper function to apply or remove aggregations to a given search source used for gaining data - * for Discover's histogram vis + * Helper function to get the agg configs required for the unified histogram chart request */ -export function getChartAggConfigs( - searchSource: ISearchSource, - histogramInterval: string, - data: DataPublicPluginStart -) { - const dataView = searchSource.getField('index')!; +export function getChartAggConfigs({ + dataView, + timeInterval, + data, +}: { + dataView: DataView; + timeInterval: string; + data: DataPublicPluginStart; +}) { const visStateAggs = [ { type: 'count', @@ -27,7 +31,7 @@ export function getChartAggConfigs( schema: 'segment', params: { field: dataView.timeFieldName!, - interval: histogramInterval, + interval: timeInterval, timeRange: data.query.timefilter.timefilter.getTime(), }, }, diff --git a/src/plugins/discover/public/application/main/utils/get_dimensions.test.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts similarity index 78% rename from src/plugins/discover/public/application/main/utils/get_dimensions.test.ts rename to src/plugins/unified_histogram/public/chart/get_dimensions.test.ts index 2de9acace965c..fd26fa20ce793 100644 --- a/src/plugins/discover/public/application/main/utils/get_dimensions.test.ts +++ b/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts @@ -5,26 +5,15 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { getDimensions } from './get_dimensions'; -import { dataViewWithTimefieldMock } from '../../../__mocks__/data_view_with_timefield'; -import { ISearchSource, calculateBounds } from '@kbn/data-plugin/public'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { calculateBounds } from '@kbn/data-plugin/public'; import { getChartAggConfigs } from './get_chart_agg_configs'; test('getDimensions', () => { const dataView = dataViewWithTimefieldMock; - const setField = jest.fn(); - const searchSource = { - setField, - removeField: jest.fn(), - getField: (name: string) => { - if (name === 'index') { - return dataView; - } - }, - } as unknown as ISearchSource; - const dataMock = dataPluginMock.createStartContract(); dataMock.query.timefilter.timefilter.getTime = () => { return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; @@ -32,8 +21,7 @@ test('getDimensions', () => { dataMock.query.timefilter.timefilter.calculateBounds = (timeRange) => { return calculateBounds(timeRange); }; - - const aggsConfig = getChartAggConfigs(searchSource, 'auto', dataMock); + const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); const actual = getDimensions(aggsConfig!, dataMock); expect(actual).toMatchInlineSnapshot(` Object { diff --git a/src/plugins/discover/public/application/main/utils/get_dimensions.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.ts similarity index 95% rename from src/plugins/discover/public/application/main/utils/get_dimensions.ts rename to src/plugins/unified_histogram/public/chart/get_dimensions.ts index a1ea11609b8ca..94ed3d4540d21 100644 --- a/src/plugins/discover/public/application/main/utils/get_dimensions.ts +++ b/src/plugins/unified_histogram/public/chart/get_dimensions.ts @@ -5,10 +5,11 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + import moment from 'moment'; import dateMath from '@kbn/datemath'; import { DataPublicPluginStart, search, IAggConfigs } from '@kbn/data-plugin/public'; -import { Dimensions, HistogramParamsBounds } from '../components/chart/point_series'; +import type { Dimensions, HistogramParamsBounds } from '../types'; export function getDimensions( aggs: IAggConfigs, diff --git a/src/plugins/unified_histogram/public/chart/histogram.test.tsx b/src/plugins/unified_histogram/public/chart/histogram.test.tsx new file mode 100644 index 0000000000000..3e1213978e385 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/histogram.test.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; +import { Histogram } from './histogram'; +import React from 'react'; +import { unifiedHistogramServicesMock } from '../__mocks__/services'; + +const chartData = { + xAxisOrderedValues: [ + 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, + 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, + 1624917600000, 1625004000000, 1625090400000, + ], + xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, + xAxisLabel: 'order_date per day', + yAxisFormat: { id: 'number' }, + ordered: { + date: true, + interval: { + asMilliseconds: jest.fn(), + }, + intervalESUnit: 'd', + intervalESValue: 1, + min: '2021-03-18T08:28:56.411Z', + max: '2021-07-01T07:28:56.411Z', + }, + yAxisLabel: 'Count', + values: [ + { x: 1623880800000, y: 134 }, + { x: 1623967200000, y: 152 }, + { x: 1624053600000, y: 141 }, + { x: 1624140000000, y: 138 }, + { x: 1624226400000, y: 142 }, + { x: 1624312800000, y: 157 }, + { x: 1624399200000, y: 149 }, + { x: 1624485600000, y: 146 }, + { x: 1624572000000, y: 170 }, + { x: 1624658400000, y: 137 }, + { x: 1624744800000, y: 150 }, + { x: 1624831200000, y: 144 }, + { x: 1624917600000, y: 147 }, + { x: 1625004000000, y: 137 }, + { x: 1625090400000, y: 66 }, + ], +} as unknown as UnifiedHistogramChartData; + +function mountComponent( + status: UnifiedHistogramFetchStatus, + data: UnifiedHistogramChartData | null = chartData, + error?: Error +) { + const services = unifiedHistogramServicesMock; + services.data.query.timefilter.timefilter.getAbsoluteTime = () => { + return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; + }; + + const timefilterUpdateHandler = jest.fn(); + + const props = { + services: unifiedHistogramServicesMock, + chart: { + status, + hidden: false, + timeInterval: 'auto', + bucketInterval: { + scaled: true, + description: 'test', + scale: 2, + }, + data: data ?? undefined, + error, + }, + timefilterUpdateHandler, + }; + + return mountWithIntl(); +} + +describe('Histogram', () => { + it('renders correctly', () => { + const component = mountComponent('complete'); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); + }); + + it('renders error correctly', () => { + const component = mountComponent('error', null, new Error('Loading error')); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(false); + expect(component.find('[data-test-subj="unifiedHistogramErrorChartContainer"]').exists()).toBe( + true + ); + expect( + component.find('[data-test-subj="unifiedHistogramErrorChartText"]').get(1).props.children + ).toBe('Loading error'); + }); + + it('renders loading state correctly', () => { + const component = mountComponent('loading', null); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); + expect(component.find('[data-test-subj="unifiedHistogramChartLoading"]').exists()).toBe(true); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/chart/histogram.tsx b/src/plugins/unified_histogram/public/chart/histogram.tsx similarity index 73% rename from src/plugins/discover/public/application/main/components/chart/histogram.tsx rename to src/plugins/unified_histogram/public/chart/histogram.tsx index 62ade96fceb86..a201258e49bf2 100644 --- a/src/plugins/discover/public/application/main/components/chart/histogram.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.tsx @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import './histogram.scss'; + import moment, { unitOfTime } from 'moment-timezone'; import React, { useCallback, useMemo } from 'react'; import { @@ -16,23 +16,26 @@ import { EuiLoadingChart, EuiSpacer, EuiText, + useEuiTheme, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import dateMath from '@kbn/datemath'; +import type { + BrushEndListener, + ElementClickListener, + XYBrushEvent, + XYChartElementEvent, +} from '@elastic/charts'; import { Axis, - BrushEndListener, Chart, - ElementClickListener, HistogramBarSeries, Position, ScaleType, Settings, TooltipType, - XYBrushEvent, - XYChartElementEvent, } from '@elastic/charts'; -import { IUiSettingsClient } from '@kbn/core/public'; +import type { IUiSettingsClient } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { CurrentTime, @@ -42,16 +45,12 @@ import { } from '@kbn/charts-plugin/public'; import { LEGACY_TIME_AXIS, MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; import { css } from '@emotion/react'; -import { useDiscoverServices } from '../../../../hooks/use_discover_services'; -import { DataCharts$, DataChartsMessage } from '../../hooks/use_saved_search'; -import { FetchStatus } from '../../../types'; -import { useDataState } from '../../hooks/use_data_state'; -import { GetStateReturn } from '../../services/discover_state'; +import type { UnifiedHistogramChartContext, UnifiedHistogramServices } from '../types'; -export interface DiscoverHistogramProps { - savedSearchData$: DataCharts$; +export interface HistogramProps { + services: UnifiedHistogramServices; + chart: UnifiedHistogramChartContext; timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; - stateContainer: GetStateReturn; } function getTimezone(uiSettings: IUiSettingsClient) { @@ -64,19 +63,14 @@ function getTimezone(uiSettings: IUiSettingsClient) { } } -export function DiscoverHistogram({ - savedSearchData$, +export function Histogram({ + services: { data, theme, uiSettings, fieldFormats }, + chart: { status, timeInterval, bucketInterval, data: chartData, error }, timefilterUpdateHandler, - stateContainer, -}: DiscoverHistogramProps) { - const { data, theme, uiSettings, fieldFormats } = useDiscoverServices(); +}: HistogramProps) { const chartTheme = theme.useChartsTheme(); const chartBaseTheme = theme.useChartsBaseTheme(); - - const dataState: DataChartsMessage = useDataState(savedSearchData$); - const timeZone = getTimezone(uiSettings); - const { chartData, bucketInterval, fetchStatus, error } = dataState; const onBrushEnd = useCallback( ({ x }: XYBrushEvent) => { @@ -105,7 +99,6 @@ export function DiscoverHistogram({ ); const { timefilter } = data.query.timefilter; - const { from, to } = timefilter.getAbsoluteTime(); const dateFormat = useMemo(() => uiSettings.get('dateFormat'), [uiSettings]); @@ -127,12 +120,12 @@ export function DiscoverHistogram({ from: dateMath.parse(from), to: dateMath.parse(to, { roundUp: true }), }; - const intervalText = i18n.translate('discover.histogramTimeRangeIntervalDescription', { + const intervalText = i18n.translate('unifiedHistogram.histogramTimeRangeIntervalDescription', { defaultMessage: '(interval: {value})', values: { value: `${ - stateContainer.appStateContainer.getState().interval === 'auto' - ? `${i18n.translate('discover.histogramTimeRangeIntervalAuto', { + timeInterval === 'auto' + ? `${i18n.translate('unifiedHistogram.histogramTimeRangeIntervalAuto', { defaultMessage: 'Auto', })} - ` : '' @@ -140,39 +133,71 @@ export function DiscoverHistogram({ }, }); return `${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${intervalText}`; - }, [from, to, toMoment, bucketInterval, stateContainer]); + }, [from, to, timeInterval, bucketInterval?.description, toMoment]); + + const { euiTheme } = useEuiTheme(); + const chartCss = css` + flex-grow: 1; + padding: 0 ${euiTheme.size.s} ${euiTheme.size.s} ${euiTheme.size.s}; + `; + + if (!chartData && status === 'loading') { + const chartLoadingCss = css` + display: flex; + flex-direction: column; + justify-content: center; + flex: 1 0 100%; + text-align: center; + height: 100%; + width: 100%; + `; - if (!chartData && fetchStatus === FetchStatus.LOADING) { return ( -
      -
      +
      +
      - +
      ); } - if (fetchStatus === FetchStatus.ERROR && error) { + if (status === 'error' && error) { + const chartErrorContainerCss = css` + padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; + `; + const chartErrorIconCss = css` + padding-top: 0.5 * ${euiTheme.size.xs}; + `; + const chartErrorCss = css` + margin-left: ${euiTheme.size.xs} !important; + `; + const chartErrorTextCss = css` + margin-top: ${euiTheme.size.s}; + `; + return ( -
      +
      - + - + - + {error.message}
      @@ -227,28 +252,31 @@ export function DiscoverHistogram({ const useLegacyTimeAxis = uiSettings.get(LEGACY_TIME_AXIS, false); - const toolTipTitle = i18n.translate('discover.timeIntervalWithValueWarning', { + const toolTipTitle = i18n.translate('unifiedHistogram.timeIntervalWithValueWarning', { defaultMessage: 'Warning', }); - const toolTipContent = i18n.translate('discover.bucketIntervalTooltip', { + const toolTipContent = i18n.translate('unifiedHistogram.bucketIntervalTooltip', { defaultMessage: 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}.', values: { bucketsDescription: bucketInterval!.scale && bucketInterval!.scale > 1 - ? i18n.translate('discover.bucketIntervalTooltip.tooLargeBucketsText', { + ? i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooLargeBucketsText', { defaultMessage: 'buckets that are too large', }) - : i18n.translate('discover.bucketIntervalTooltip.tooManyBucketsText', { + : i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooManyBucketsText', { defaultMessage: 'too many buckets', }), bucketIntervalDescription: bucketInterval?.description, }, }); + const timeRangeCss = css` + padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; + `; let timeRange = ( - + {timeRangeText} ); @@ -274,7 +302,7 @@ export function DiscoverHistogram({ return ( -
      +
      xAxisFormatter.convert(value)} /> { const { result } = renderHook(() => { return useChartPanels({ toggleHideChart: jest.fn(), - onChangeInterval: jest.fn(), + onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), onResetChartHeight: jest.fn(), - hideChart: true, - interval: 'auto', + chart: { + status: 'complete', + hidden: true, + timeInterval: 'auto', + }, }); }); const panels: EuiContextMenuPanelDescriptor[] = result.current; @@ -33,11 +35,14 @@ describe('test useChartPanels', () => { const { result } = renderHook(() => { return useChartPanels({ toggleHideChart: jest.fn(), - onChangeInterval: jest.fn(), + onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), onResetChartHeight: jest.fn(), - hideChart: false, - interval: 'auto', + chart: { + status: 'complete', + hidden: false, + timeInterval: 'auto', + }, }); }); const panels: EuiContextMenuPanelDescriptor[] = result.current; @@ -51,10 +56,13 @@ describe('test useChartPanels', () => { const { result } = renderHook(() => { return useChartPanels({ toggleHideChart: jest.fn(), - onChangeInterval: jest.fn(), + onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), - hideChart: false, - interval: 'auto', + chart: { + status: 'complete', + hidden: false, + timeInterval: 'auto', + }, }); }); const panel0: EuiContextMenuPanelDescriptor = result.current[0]; @@ -66,11 +74,14 @@ describe('test useChartPanels', () => { const { result } = renderHook(() => { return useChartPanels({ toggleHideChart: jest.fn(), - onChangeInterval: jest.fn(), + onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), onResetChartHeight, - hideChart: false, - interval: 'auto', + chart: { + status: 'complete', + hidden: false, + timeInterval: 'auto', + }, }); }); const panel0: EuiContextMenuPanelDescriptor = result.current[0]; diff --git a/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts similarity index 65% rename from src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts rename to src/plugins/unified_histogram/public/chart/use_chart_panels.ts index f01c72aaee997..dd6f162b352f6 100644 --- a/src/plugins/discover/public/application/main/components/chart/use_chart_panels.ts +++ b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts @@ -5,29 +5,35 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ + import { i18n } from '@kbn/i18n'; import type { EuiContextMenuPanelItemDescriptor, EuiContextMenuPanelDescriptor, } from '@elastic/eui'; import { search } from '@kbn/data-plugin/public'; +import type { UnifiedHistogramChartContext } from '../types'; export function useChartPanels({ + chart, toggleHideChart, - onChangeInterval, + onTimeIntervalChange, closePopover, onResetChartHeight, - hideChart, - interval, }: { + chart?: UnifiedHistogramChartContext; toggleHideChart: () => void; - onChangeInterval: (value: string) => void; + onTimeIntervalChange: (timeInterval: string) => void; closePopover: () => void; onResetChartHeight?: () => void; - hideChart?: boolean; - interval?: string; }) { - const selectedOptionIdx = search.aggs.intervalOptions.findIndex((opt) => opt.val === interval); + if (!chart) { + return []; + } + + const selectedOptionIdx = search.aggs.intervalOptions.findIndex( + (opt) => opt.val === chart.timeInterval + ); const intervalDisplay = selectedOptionIdx > -1 ? search.aggs.intervalOptions[selectedOptionIdx].display @@ -35,25 +41,25 @@ export function useChartPanels({ const mainPanelItems: EuiContextMenuPanelItemDescriptor[] = [ { - name: !hideChart - ? i18n.translate('discover.hideChart', { + name: !chart.hidden + ? i18n.translate('unifiedHistogram.hideChart', { defaultMessage: 'Hide chart', }) - : i18n.translate('discover.showChart', { + : i18n.translate('unifiedHistogram.showChart', { defaultMessage: 'Show chart', }), - icon: !hideChart ? 'eyeClosed' : 'eye', + icon: !chart.hidden ? 'eyeClosed' : 'eye', onClick: () => { toggleHideChart(); closePopover(); }, - 'data-test-subj': 'discoverChartToggle', + 'data-test-subj': 'unifiedHistogramChartToggle', }, ]; - if (!hideChart) { + if (!chart.hidden) { if (onResetChartHeight) { mainPanelItems.push({ - name: i18n.translate('discover.resetChartHeight', { + name: i18n.translate('unifiedHistogram.resetChartHeight', { defaultMessage: 'Reset to default height', }), icon: 'refresh', @@ -61,36 +67,36 @@ export function useChartPanels({ onResetChartHeight(); closePopover(); }, - 'data-test-subj': 'discoverChartResetHeight', + 'data-test-subj': 'unifiedHistogramChartResetHeight', }); } mainPanelItems.push({ - name: i18n.translate('discover.timeIntervalWithValue', { + name: i18n.translate('unifiedHistogram.timeIntervalWithValue', { defaultMessage: 'Time interval: {timeInterval}', values: { timeInterval: intervalDisplay, }, }), panel: 1, - 'data-test-subj': 'discoverTimeIntervalPanel', + 'data-test-subj': 'unifiedHistogramTimeIntervalPanel', }); } const panels: EuiContextMenuPanelDescriptor[] = [ { id: 0, - title: i18n.translate('discover.chartOptions', { + title: i18n.translate('unifiedHistogram.chartOptions', { defaultMessage: 'Chart options', }), items: mainPanelItems, }, ]; - if (!hideChart) { + if (!chart.hidden) { panels.push({ id: 1, initialFocusedItemIndex: selectedOptionIdx > -1 ? selectedOptionIdx : 0, - title: i18n.translate('discover.timeIntervals', { + title: i18n.translate('unifiedHistogram.timeIntervals', { defaultMessage: 'Time intervals', }), items: search.aggs.intervalOptions @@ -99,13 +105,13 @@ export function useChartPanels({ return { name: display, label: display, - icon: val === interval ? 'check' : 'empty', + icon: val === chart.timeInterval ? 'check' : 'empty', onClick: () => { - onChangeInterval(val); + onTimeIntervalChange(val); closePopover(); }, - 'data-test-subj': `discoverTimeInterval-${display}`, - className: val === interval ? 'discoverIntervalSelected' : '', + 'data-test-subj': `unifiedHistogramTimeInterval-${display}`, + className: val === chart.timeInterval ? 'unifiedHistogramIntervalSelected' : '', }; }), }); diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx new file mode 100644 index 0000000000000..d094fef953af8 --- /dev/null +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import type { ReactWrapper } from 'enzyme'; +import type { HitsCounterProps } from './hits_counter'; +import { HitsCounter } from './hits_counter'; +import { findTestSubject } from '@elastic/eui/lib/test'; +import { EuiLoadingSpinner } from '@elastic/eui'; + +describe('hits counter', function () { + let props: HitsCounterProps; + let component: ReactWrapper; + + beforeAll(() => { + props = { + hits: { + status: 'complete', + total: 2, + }, + }; + }); + + it('expect to render the number of hits', function () { + component = mountWithIntl(); + const hits = findTestSubject(component, 'unifiedHistogramQueryHits'); + expect(hits.text()).toBe('2'); + }); + + it('expect to render 1,899 hits if 1899 hits given', function () { + component = mountWithIntl( + + ); + const hits = findTestSubject(component, 'unifiedHistogramQueryHits'); + expect(hits.text()).toBe('1,899'); + }); + + it('should render the element passed to the append prop', () => { + const appendHitsCounter =
      appendHitsCounter
      ; + component = mountWithIntl(); + expect(findTestSubject(component, 'appendHitsCounter').length).toBe(1); + }); + + it('should render a EuiLoadingSpinner when status is partial', () => { + component = mountWithIntl(); + expect(component.find(EuiLoadingSpinner).length).toBe(1); + }); + + it('should render unifiedHistogramQueryHitsPartial when status is partial', () => { + component = mountWithIntl(); + expect(component.find('[data-test-subj="unifiedHistogramQueryHitsPartial"]').length).toBe(1); + }); + + it('should render unifiedHistogramQueryHits when status is complete', () => { + component = mountWithIntl(); + expect(component.find('[data-test-subj="unifiedHistogramQueryHits"]').length).toBe(1); + }); +}); diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx new file mode 100644 index 0000000000000..39df40650557c --- /dev/null +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { ReactElement } from 'react'; +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLoadingSpinner } from '@elastic/eui'; +import { FormattedMessage, FormattedNumber } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import type { UnifiedHistogramHitsContext } from '../types'; + +export interface HitsCounterProps { + hits: UnifiedHistogramHitsContext; + append?: ReactElement; +} + +export function HitsCounter({ hits, append }: HitsCounterProps) { + if (!hits.total && hits.status === 'loading') { + return null; + } + + const formattedHits = ( + + + + ); + + const hitsCounterCss = css` + flex-grow: 0; + `; + + return ( + + + + {hits.status === 'partial' && ( + + )} + {hits.status !== 'partial' && ( + + )} + + + {hits.status === 'partial' && ( + + + + )} + {append} + + ); +} diff --git a/src/plugins/discover/public/application/main/components/hits_counter/index.ts b/src/plugins/unified_histogram/public/hits_counter/index.ts similarity index 100% rename from src/plugins/discover/public/application/main/components/hits_counter/index.ts rename to src/plugins/unified_histogram/public/hits_counter/index.ts diff --git a/src/plugins/unified_histogram/public/index.ts b/src/plugins/unified_histogram/public/index.ts new file mode 100644 index 0000000000000..4d3ab5d097831 --- /dev/null +++ b/src/plugins/unified_histogram/public/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { UnifiedHistogramPublicPlugin } from './plugin'; + +export type { UnifiedHistogramLayoutProps } from './layout'; +export { UnifiedHistogramLayout } from './layout'; +export { getChartAggConfigs, buildChartData } from './chart'; +export type { + UnifiedHistogramServices, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, + UnifiedHistogramChartContext, + UnifiedHistogramChartData, + UnifiedHistogramBucketInterval, +} from './types'; + +export const plugin = () => new UnifiedHistogramPublicPlugin(); diff --git a/src/plugins/unified_histogram/public/layout/index.tsx b/src/plugins/unified_histogram/public/layout/index.tsx new file mode 100644 index 0000000000000..a729bdff0871c --- /dev/null +++ b/src/plugins/unified_histogram/public/layout/index.tsx @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiDelayRender, EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui'; +import { withSuspense } from '@kbn/shared-ux-utility'; +import React, { lazy } from 'react'; + +export type { UnifiedHistogramLayoutProps } from './layout'; + +const LazyUnifiedHistogramLayout = lazy(() => import('./layout')); + +/** + * A resizable layout component with two panels that renders a histogram with a hits + * counter in the top panel, and a main display (data table, etc.) in the bottom panel. + * If all context props are left undefined, the layout will render in a single panel + * mode including only the main display. + */ +export const UnifiedHistogramLayout = withSuspense( + LazyUnifiedHistogramLayout, + + + + + +); diff --git a/src/plugins/unified_histogram/public/layout/layout.test.tsx b/src/plugins/unified_histogram/public/layout/layout.test.tsx new file mode 100644 index 0000000000000..73b97c8f64def --- /dev/null +++ b/src/plugins/unified_histogram/public/layout/layout.test.tsx @@ -0,0 +1,192 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import type { ReactWrapper } from 'enzyme'; +import React from 'react'; +import { act } from 'react-dom/test-utils'; +import { Chart } from '../chart'; +import { Panels, PANELS_MODE } from '../panels'; +import type { UnifiedHistogramChartContext, UnifiedHistogramHitsContext } from '../types'; +import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { UnifiedHistogramLayout, UnifiedHistogramLayoutProps } from './layout'; + +let mockBreakpoint = 'l'; + +jest.mock('@elastic/eui', () => { + const original = jest.requireActual('@elastic/eui'); + return { + ...original, + useIsWithinBreakpoints: (breakpoints: string[]) => { + return breakpoints.includes(mockBreakpoint); + }, + }; +}); + +describe('Layout', () => { + const createHits = (): UnifiedHistogramHitsContext => ({ + status: 'complete', + total: 10, + }); + + const createChart = (): UnifiedHistogramChartContext => ({ + status: 'complete', + hidden: false, + timeInterval: 'auto', + bucketInterval: { + scaled: true, + description: 'test', + scale: 2, + }, + }); + + const mountComponent = async ({ + services = unifiedHistogramServicesMock, + hits = createHits(), + chart = createChart(), + resizeRef = { current: null }, + ...rest + }: Partial> & { + hits?: UnifiedHistogramHitsContext | null; + chart?: UnifiedHistogramChartContext | null; + } = {}) => { + services.data.query.timefilter.timefilter.getAbsoluteTime = () => { + return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; + }; + + const component = mountWithIntl( + + ); + + return component; + }; + + const setBreakpoint = (component: ReactWrapper, breakpoint: string) => { + mockBreakpoint = breakpoint; + component.setProps({}).update(); + }; + + beforeEach(() => { + mockBreakpoint = 'l'; + }); + + describe('PANELS_MODE', () => { + it('should set the panels mode to PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => { + const component = await mountComponent(); + setBreakpoint(component, 'm'); + expect(component.find(Panels).prop('mode')).toBe(PANELS_MODE.RESIZABLE); + }); + + it('should set the panels mode to PANELS_MODE.FIXED when viewing on small screens and below', async () => { + const component = await mountComponent(); + setBreakpoint(component, 's'); + expect(component.find(Panels).prop('mode')).toBe(PANELS_MODE.FIXED); + }); + + it('should set the panels mode to PANELS_MODE.FIXED if chart.hidden is true', async () => { + const component = await mountComponent({ + chart: { + ...createChart(), + hidden: true, + }, + }); + expect(component.find(Panels).prop('mode')).toBe(PANELS_MODE.FIXED); + }); + + it('should set the panels mode to PANELS_MODE.FIXED if chart is undefined', async () => { + const component = await mountComponent({ chart: null }); + expect(component.find(Panels).prop('mode')).toBe(PANELS_MODE.FIXED); + }); + + it('should set the panels mode to PANELS_MODE.SINGLE if chart and hits are undefined', async () => { + const component = await mountComponent({ chart: null, hits: null }); + expect(component.find(Panels).prop('mode')).toBe(PANELS_MODE.SINGLE); + }); + + it('should set a fixed height for Chart when panels mode is PANELS_MODE.FIXED and chart.hidden is false', async () => { + const component = await mountComponent(); + setBreakpoint(component, 's'); + const expectedHeight = component.find(Panels).prop('topPanelHeight'); + expect(component.find(Chart).childAt(0).getDOMNode()).toHaveStyle({ + height: `${expectedHeight}px`, + }); + }); + + it('should not set a fixed height for Chart when panels mode is PANELS_MODE.FIXED and chart.hidden is true', async () => { + const component = await mountComponent({ chart: { ...createChart(), hidden: true } }); + setBreakpoint(component, 's'); + const expectedHeight = component.find(Panels).prop('topPanelHeight'); + expect(component.find(Chart).childAt(0).getDOMNode()).not.toHaveStyle({ + height: `${expectedHeight}px`, + }); + }); + + it('should not set a fixed height for Chart when panels mode is PANELS_MODE.FIXED and chart is undefined', async () => { + const component = await mountComponent({ chart: null }); + setBreakpoint(component, 's'); + const expectedHeight = component.find(Panels).prop('topPanelHeight'); + expect(component.find(Chart).childAt(0).getDOMNode()).not.toHaveStyle({ + height: `${expectedHeight}px`, + }); + }); + + it('should pass undefined for onResetChartHeight to Chart when panels mode is PANELS_MODE.FIXED', async () => { + const component = await mountComponent({ topPanelHeight: 123 }); + expect(component.find(Chart).prop('onResetChartHeight')).toBeDefined(); + setBreakpoint(component, 's'); + expect(component.find(Chart).prop('onResetChartHeight')).toBeUndefined(); + }); + }); + + describe('topPanelHeight', () => { + it('should pass a default topPanelHeight to Panels when the topPanelHeight prop is undefined', async () => { + const component = await mountComponent({ topPanelHeight: undefined }); + expect(component.find(Panels).prop('topPanelHeight')).toBeGreaterThan(0); + }); + + it('should reset the topPanelHeight to the default when onResetChartHeight is called on Chart', async () => { + const component: ReactWrapper = await mountComponent({ + onTopPanelHeightChange: jest.fn((topPanelHeight) => { + component.setProps({ topPanelHeight }); + }), + }); + const defaultTopPanelHeight = component.find(Panels).prop('topPanelHeight'); + const newTopPanelHeight = 123; + expect(component.find(Panels).prop('topPanelHeight')).not.toBe(newTopPanelHeight); + act(() => { + component.find(Panels).prop('onTopPanelHeightChange')!(newTopPanelHeight); + }); + expect(component.find(Panels).prop('topPanelHeight')).toBe(newTopPanelHeight); + act(() => { + component.find(Chart).prop('onResetChartHeight')!(); + }); + expect(component.find(Panels).prop('topPanelHeight')).toBe(defaultTopPanelHeight); + }); + + it('should pass undefined for onResetChartHeight to Chart when the chart is the default height', async () => { + const component = await mountComponent({ + topPanelHeight: 123, + onTopPanelHeightChange: jest.fn((topPanelHeight) => { + component.setProps({ topPanelHeight }); + }), + }); + expect(component.find(Chart).prop('onResetChartHeight')).toBeDefined(); + act(() => { + component.find(Chart).prop('onResetChartHeight')!(); + }); + component.update(); + expect(component.find(Chart).prop('onResetChartHeight')).toBeUndefined(); + }); + }); +}); diff --git a/src/plugins/unified_histogram/public/layout/layout.tsx b/src/plugins/unified_histogram/public/layout/layout.tsx new file mode 100644 index 0000000000000..229d8a922e465 --- /dev/null +++ b/src/plugins/unified_histogram/public/layout/layout.tsx @@ -0,0 +1,149 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiSpacer, useEuiTheme, useIsWithinBreakpoints } from '@elastic/eui'; +import type { PropsWithChildren, ReactElement, RefObject } from 'react'; +import React, { useMemo } from 'react'; +import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal'; +import { css } from '@emotion/css'; +import { Chart } from '../chart'; +import { Panels, PANELS_MODE } from '../panels'; +import type { + UnifiedHistogramChartContext, + UnifiedHistogramServices, + UnifiedHistogramHitsContext, +} from '../types'; + +export interface UnifiedHistogramLayoutProps extends PropsWithChildren { + className?: string; + services: UnifiedHistogramServices; + /** + * Context object for the hits count -- leave undefined to hide the hits count + */ + hits?: UnifiedHistogramHitsContext; + /** + * Context object for the chart -- leave undefined to hide the chart + */ + chart?: UnifiedHistogramChartContext; + /** + * Ref to the element wrapping the layout which will be used for resize calculations + */ + resizeRef: RefObject; + /** + * Current top panel height -- leave undefined to use the default + */ + topPanelHeight?: number; + /** + * Append a custom element to the right of the hits count + */ + appendHitsCounter?: ReactElement; + /** + * Callback to update the topPanelHeight prop when a resize is triggered + */ + onTopPanelHeightChange?: (topPanelHeight: number | undefined) => void; + /** + * Callback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button + */ + onEditVisualization?: () => void; + /** + * Callback to hide or show the chart -- should set {@link UnifiedHistogramChartContext.hidden} to chartHidden + */ + onChartHiddenChange?: (chartHidden: boolean) => void; + /** + * Callback to update the time interval -- should set {@link UnifiedHistogramChartContext.timeInterval} to timeInterval + */ + onTimeIntervalChange?: (timeInterval: string) => void; +} + +export const UnifiedHistogramLayout = ({ + className, + services, + hits, + chart, + resizeRef, + topPanelHeight, + appendHitsCounter, + onTopPanelHeightChange, + onEditVisualization, + onChartHiddenChange, + onTimeIntervalChange, + children, +}: UnifiedHistogramLayoutProps) => { + const topPanelNode = useMemo( + () => createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } }), + [] + ); + + const mainPanelNode = useMemo( + () => createHtmlPortalNode({ attributes: { class: 'eui-fullHeight' } }), + [] + ); + + const isMobile = useIsWithinBreakpoints(['xs', 's']); + const showFixedPanels = isMobile || !chart || chart.hidden; + const { euiTheme } = useEuiTheme(); + const defaultTopPanelHeight = euiTheme.base * 12; + const minTopPanelHeight = euiTheme.base * 8; + const minMainPanelHeight = euiTheme.base * 10; + + const chartClassName = + isMobile && chart && !chart.hidden + ? css` + height: ${defaultTopPanelHeight}px; + ` + : 'eui-fullHeight'; + + const panelsMode = + chart || hits + ? showFixedPanels + ? PANELS_MODE.FIXED + : PANELS_MODE.RESIZABLE + : PANELS_MODE.SINGLE; + + const currentTopPanelHeight = topPanelHeight ?? defaultTopPanelHeight; + + const onResetChartHeight = useMemo(() => { + return currentTopPanelHeight !== defaultTopPanelHeight && panelsMode === PANELS_MODE.RESIZABLE + ? () => onTopPanelHeightChange?.(undefined) + : undefined; + }, [currentTopPanelHeight, defaultTopPanelHeight, onTopPanelHeightChange, panelsMode]); + + return ( + <> + + : } + onEditVisualization={onEditVisualization} + onResetChartHeight={onResetChartHeight} + onChartHiddenChange={onChartHiddenChange} + onTimeIntervalChange={onTimeIntervalChange} + /> + + {children} + } + mainPanel={} + onTopPanelHeightChange={onTopPanelHeightChange} + /> + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default UnifiedHistogramLayout; diff --git a/src/plugins/discover/public/application/main/components/chart/index.ts b/src/plugins/unified_histogram/public/panels/index.ts similarity index 87% rename from src/plugins/discover/public/application/main/components/chart/index.ts rename to src/plugins/unified_histogram/public/panels/index.ts index d5d5a85d1d0f2..ba3e73cb5a35a 100644 --- a/src/plugins/discover/public/application/main/components/chart/index.ts +++ b/src/plugins/unified_histogram/public/panels/index.ts @@ -6,4 +6,4 @@ * Side Public License, v 1. */ -export { DiscoverChart } from './discover_chart'; +export { Panels, PANELS_MODE } from './panels'; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx b/src/plugins/unified_histogram/public/panels/panels.test.tsx similarity index 54% rename from src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx rename to src/plugins/unified_histogram/public/panels/panels.test.tsx index c136675494fb3..e0e2de24b4083 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels.test.tsx +++ b/src/plugins/unified_histogram/public/panels/panels.test.tsx @@ -7,14 +7,15 @@ */ import { mount } from 'enzyme'; -import React, { ReactElement, RefObject } from 'react'; -import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels'; -import { DiscoverPanelsResizable } from './discover_panels_resizable'; -import { DiscoverPanelsFixed } from './discover_panels_fixed'; +import type { ReactElement, RefObject } from 'react'; +import React from 'react'; +import { Panels, PANELS_MODE } from './panels'; +import { PanelsResizable } from './panels_resizable'; +import { PanelsFixed } from './panels_fixed'; -describe('Discover panels component', () => { +describe('Panels component', () => { const mountComponent = ({ - mode = DISCOVER_PANELS_MODE.RESIZABLE, + mode = PANELS_MODE.RESIZABLE, resizeRef = { current: null }, initialTopPanelHeight = 200, minTopPanelHeight = 100, @@ -22,7 +23,7 @@ describe('Discover panels component', () => { topPanel = <>, mainPanel = <>, }: { - mode?: DISCOVER_PANELS_MODE; + mode?: PANELS_MODE; resizeRef?: RefObject; initialTopPanelHeight?: number; minTopPanelHeight?: number; @@ -31,7 +32,7 @@ describe('Discover panels component', () => { topPanel?: ReactElement; }) => { return mount( - { ); }; - it('should show DiscoverPanelsFixed when mode is DISCOVER_PANELS_MODE.SINGLE', () => { + it('should show PanelsFixed when mode is PANELS_MODE.SINGLE', () => { const topPanel =
      ; const mainPanel =
      ; - const component = mountComponent({ mode: DISCOVER_PANELS_MODE.SINGLE, topPanel, mainPanel }); - expect(component.find(DiscoverPanelsFixed).exists()).toBe(true); - expect(component.find(DiscoverPanelsResizable).exists()).toBe(false); + const component = mountComponent({ mode: PANELS_MODE.SINGLE, topPanel, mainPanel }); + expect(component.find(PanelsFixed).exists()).toBe(true); + expect(component.find(PanelsResizable).exists()).toBe(false); expect(component.contains(topPanel)).toBe(false); expect(component.contains(mainPanel)).toBe(true); }); - it('should show DiscoverPanelsFixed when mode is DISCOVER_PANELS_MODE.FIXED', () => { + it('should show PanelsFixed when mode is PANELS_MODE.FIXED', () => { const topPanel =
      ; const mainPanel =
      ; - const component = mountComponent({ mode: DISCOVER_PANELS_MODE.FIXED, topPanel, mainPanel }); - expect(component.find(DiscoverPanelsFixed).exists()).toBe(true); - expect(component.find(DiscoverPanelsResizable).exists()).toBe(false); + const component = mountComponent({ mode: PANELS_MODE.FIXED, topPanel, mainPanel }); + expect(component.find(PanelsFixed).exists()).toBe(true); + expect(component.find(PanelsResizable).exists()).toBe(false); expect(component.contains(topPanel)).toBe(true); expect(component.contains(mainPanel)).toBe(true); }); - it('should show DiscoverPanelsResizable when mode is DISCOVER_PANELS_MODE.RESIZABLE', () => { + it('should show PanelsResizable when mode is PANELS_MODE.RESIZABLE', () => { const topPanel =
      ; const mainPanel =
      ; - const component = mountComponent({ mode: DISCOVER_PANELS_MODE.RESIZABLE, topPanel, mainPanel }); - expect(component.find(DiscoverPanelsFixed).exists()).toBe(false); - expect(component.find(DiscoverPanelsResizable).exists()).toBe(true); + const component = mountComponent({ mode: PANELS_MODE.RESIZABLE, topPanel, mainPanel }); + expect(component.find(PanelsFixed).exists()).toBe(false); + expect(component.find(PanelsResizable).exists()).toBe(true); expect(component.contains(topPanel)).toBe(true); expect(component.contains(mainPanel)).toBe(true); }); - it('should pass true for hideTopPanel when mode is DISCOVER_PANELS_MODE.SINGLE', () => { + it('should pass true for hideTopPanel when mode is PANELS_MODE.SINGLE', () => { const topPanel =
      ; const mainPanel =
      ; - const component = mountComponent({ mode: DISCOVER_PANELS_MODE.SINGLE, topPanel, mainPanel }); - expect(component.find(DiscoverPanelsFixed).prop('hideTopPanel')).toBe(true); + const component = mountComponent({ mode: PANELS_MODE.SINGLE, topPanel, mainPanel }); + expect(component.find(PanelsFixed).prop('hideTopPanel')).toBe(true); expect(component.contains(topPanel)).toBe(false); expect(component.contains(mainPanel)).toBe(true); }); - it('should pass false for hideTopPanel when mode is DISCOVER_PANELS_MODE.FIXED', () => { + it('should pass false for hideTopPanel when mode is PANELS_MODE.FIXED', () => { const topPanel =
      ; const mainPanel =
      ; - const component = mountComponent({ mode: DISCOVER_PANELS_MODE.FIXED, topPanel, mainPanel }); - expect(component.find(DiscoverPanelsFixed).prop('hideTopPanel')).toBe(false); + const component = mountComponent({ mode: PANELS_MODE.FIXED, topPanel, mainPanel }); + expect(component.find(PanelsFixed).prop('hideTopPanel')).toBe(false); expect(component.contains(topPanel)).toBe(true); expect(component.contains(mainPanel)).toBe(true); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx b/src/plugins/unified_histogram/public/panels/panels.tsx similarity index 64% rename from src/plugins/discover/public/application/main/components/layout/discover_panels.tsx rename to src/plugins/unified_histogram/public/panels/panels.tsx index b79d9fb96aaeb..609219ab28666 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels.tsx +++ b/src/plugins/unified_histogram/public/panels/panels.tsx @@ -6,31 +6,32 @@ * Side Public License, v 1. */ -import React, { ReactElement, RefObject } from 'react'; -import { DiscoverPanelsResizable } from './discover_panels_resizable'; -import { DiscoverPanelsFixed } from './discover_panels_fixed'; +import type { ReactElement, RefObject } from 'react'; +import React from 'react'; +import { PanelsResizable } from './panels_resizable'; +import { PanelsFixed } from './panels_fixed'; -export enum DISCOVER_PANELS_MODE { +export enum PANELS_MODE { SINGLE = 'single', FIXED = 'fixed', RESIZABLE = 'resizable', } -export interface DiscoverPanelsProps { +export interface PanelsProps { className?: string; - mode: DISCOVER_PANELS_MODE; + mode: PANELS_MODE; resizeRef: RefObject; topPanelHeight: number; minTopPanelHeight: number; minMainPanelHeight: number; topPanel: ReactElement; mainPanel: ReactElement; - onTopPanelHeightChange: (height: number) => void; + onTopPanelHeightChange?: (topPanelHeight: number) => void; } -const fixedModes = [DISCOVER_PANELS_MODE.SINGLE, DISCOVER_PANELS_MODE.FIXED]; +const fixedModes = [PANELS_MODE.SINGLE, PANELS_MODE.FIXED]; -export const DiscoverPanels = ({ +export const Panels = ({ className, mode, resizeRef, @@ -40,13 +41,13 @@ export const DiscoverPanels = ({ topPanel, mainPanel, onTopPanelHeightChange, -}: DiscoverPanelsProps) => { +}: PanelsProps) => { const panelsProps = { className, topPanel, mainPanel }; return fixedModes.includes(mode) ? ( - + ) : ( - { +describe('Panels fixed', () => { const mountComponent = ({ hideTopPanel = false, topPanel = <>, @@ -21,7 +22,7 @@ describe('Discover panels fixed', () => { mainPanel: ReactElement; }) => { return mount( - + ); }; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels_fixed.tsx b/src/plugins/unified_histogram/public/panels/panels_fixed.tsx similarity index 93% rename from src/plugins/discover/public/application/main/components/layout/discover_panels_fixed.tsx rename to src/plugins/unified_histogram/public/panels/panels_fixed.tsx index 1db99e61fb8c5..1b7d8bf9bf68e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels_fixed.tsx +++ b/src/plugins/unified_histogram/public/panels/panels_fixed.tsx @@ -8,9 +8,10 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { css } from '@emotion/react'; -import React, { ReactElement } from 'react'; +import type { ReactElement } from 'react'; +import React from 'react'; -export const DiscoverPanelsFixed = ({ +export const PanelsFixed = ({ className, hideTopPanel, topPanel, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx b/src/plugins/unified_histogram/public/panels/panels_resizable.test.tsx similarity index 83% rename from src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx rename to src/plugins/unified_histogram/public/panels/panels_resizable.test.tsx index c919504091c21..a21e137e87ed7 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.test.tsx +++ b/src/plugins/unified_histogram/public/panels/panels_resizable.test.tsx @@ -6,9 +6,11 @@ * Side Public License, v 1. */ -import { mount, ReactWrapper } from 'enzyme'; -import React, { ReactElement, RefObject } from 'react'; -import { DiscoverPanelsResizable } from './discover_panels_resizable'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; +import type { ReactElement, RefObject } from 'react'; +import React from 'react'; +import { PanelsResizable } from './panels_resizable'; import { act } from 'react-dom/test-utils'; const containerHeight = 1000; @@ -23,7 +25,7 @@ jest.mock('@elastic/eui', () => ({ import * as eui from '@elastic/eui'; import { waitFor } from '@testing-library/dom'; -describe('Discover panels resizable', () => { +describe('Panels resizable', () => { const mountComponent = ({ className = '', resizeRef = { current: null }, @@ -43,10 +45,10 @@ describe('Discover panels resizable', () => { topPanel?: ReactElement; mainPanel?: ReactElement; attachTo?: HTMLElement; - onTopPanelHeightChange?: (height: number) => void; + onTopPanelHeightChange?: (topPanelHeight: number) => void; }) => { return mount( - { topPanelHeight: number ) => { const topPanelSize = (topPanelHeight / currentContainerHeight) * 100; - expect(component.find('[data-test-subj="dscResizablePanelTop"]').at(0).prop('size')).toBe( - topPanelSize - ); - expect(component.find('[data-test-subj="dscResizablePanelMain"]').at(0).prop('size')).toBe( - 100 - topPanelSize - ); + expect( + component.find('[data-test-subj="unifiedHistogramResizablePanelTop"]').at(0).prop('size') + ).toBe(topPanelSize); + expect( + component.find('[data-test-subj="unifiedHistogramResizablePanelMain"]').at(0).prop('size') + ).toBe(100 - topPanelSize); }; const forceRender = (component: ReactWrapper) => { @@ -105,7 +107,7 @@ describe('Discover panels resizable', () => { expectCorrectPanelSizes(component, containerHeight, initialTopPanelHeight); const newTopPanelSize = 30; const onPanelSizeChange = component - .find('[data-test-subj="dscResizableContainer"]') + .find('[data-test-subj="unifiedHistogramResizableContainer"]') .at(0) .prop('onPanelWidthChange') as Function; act(() => { @@ -159,12 +161,12 @@ describe('Discover panels resizable', () => { const newContainerHeight = 200; jest.spyOn(eui, 'useResizeObserver').mockReturnValue({ height: newContainerHeight, width: 0 }); forceRender(component); - expect(component.find('[data-test-subj="dscResizablePanelTop"]').at(0).prop('size')).toBe( - (minTopPanelHeight / newContainerHeight) * 100 - ); - expect(component.find('[data-test-subj="dscResizablePanelMain"]').at(0).prop('size')).toBe( - (minMainPanelHeight / newContainerHeight) * 100 - ); + expect( + component.find('[data-test-subj="unifiedHistogramResizablePanelTop"]').at(0).prop('size') + ).toBe((minTopPanelHeight / newContainerHeight) * 100); + expect( + component.find('[data-test-subj="unifiedHistogramResizablePanelMain"]').at(0).prop('size') + ).toBe((minMainPanelHeight / newContainerHeight) * 100); jest.spyOn(eui, 'useResizeObserver').mockReturnValue({ height: containerHeight, width: 0 }); forceRender(component); expectCorrectPanelSizes(component, containerHeight, initialTopPanelHeight); @@ -174,9 +176,11 @@ describe('Discover panels resizable', () => { const attachTo = document.createElement('div'); document.body.appendChild(attachTo); const component = mountComponent({ attachTo }); - const wrapper = component.find('[data-test-subj="dscResizableContainerWrapper"]'); - const resizeButton = component.find('button[data-test-subj="dsc-resizable-button"]'); - const resizeButtonInner = component.find('[data-test-subj="dscResizableButtonInner"]'); + const wrapper = component.find('[data-test-subj="unifiedHistogramResizableContainerWrapper"]'); + const resizeButton = component.find('button[data-test-subj="unifiedHistogramResizableButton"]'); + const resizeButtonInner = component.find( + '[data-test-subj="unifiedHistogramResizableButtonInner"]' + ); const mouseEvent = { pageX: 0, pageY: 0, diff --git a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx similarity index 72% rename from src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx rename to src/plugins/unified_histogram/public/panels/panels_resizable.tsx index b65da1eb0bf68..76fecd42d2aed 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_panels_resizable.tsx +++ b/src/plugins/unified_histogram/public/panels/panels_resizable.tsx @@ -6,17 +6,24 @@ * Side Public License, v 1. */ -import { EuiResizableContainer, useGeneratedHtmlId, useResizeObserver } from '@elastic/eui'; +import { + EuiResizableContainer, + useEuiTheme, + useGeneratedHtmlId, + useResizeObserver, +} from '@elastic/eui'; import { css } from '@emotion/react'; -import React, { ReactElement, RefObject, useCallback, useEffect, useState } from 'react'; +import { isEqual, round } from 'lodash'; +import type { ReactElement, RefObject } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; const percentToPixels = (containerHeight: number, percentage: number) => Math.round(containerHeight * (percentage / 100)); const pixelsToPercent = (containerHeight: number, pixels: number) => - +((pixels / containerHeight) * 100).toFixed(4); + (pixels / containerHeight) * 100; -export const DiscoverPanelsResizable = ({ +export const PanelsResizable = ({ className, resizeRef, topPanelHeight, @@ -33,7 +40,7 @@ export const DiscoverPanelsResizable = ({ minMainPanelHeight: number; topPanel: ReactElement; mainPanel: ReactElement; - onTopPanelHeightChange: (height: number) => void; + onTopPanelHeightChange?: (topPanelHeight: number) => void; }) => { const topPanelId = useGeneratedHtmlId({ prefix: 'topPanel' }); const { height: containerHeight } = useResizeObserver(resizeRef.current); @@ -65,23 +72,28 @@ export const DiscoverPanelsResizable = ({ z-index: 2; `; - // Instead of setting the panel sizes directly, we convert the top panel height - // from a percentage of the container height to a pixel value. This will trigger - // the effect below to update the panel sizes. + // We convert the top panel height from a percentage of the container height + // to a pixel value and emit the change to the parent component. We also convert + // the pixel value back to a percentage before updating the panel sizes to avoid + // rounding issues with the isEqual check in the effect below. const onPanelSizeChange = useCallback( ({ [topPanelId]: topPanelSize }: { [key: string]: number }) => { const newTopPanelHeight = percentToPixels(containerHeight, topPanelSize); + const newTopPanelSize = pixelsToPercent(containerHeight, newTopPanelHeight); - if (newTopPanelHeight !== topPanelHeight) { - onTopPanelHeightChange(newTopPanelHeight); - } + setPanelSizes({ + topPanelSize: round(newTopPanelSize, 4), + mainPanelSize: round(100 - newTopPanelSize, 4), + }); + + onTopPanelHeightChange?.(newTopPanelHeight); }, - [containerHeight, onTopPanelHeightChange, topPanelHeight, topPanelId] + [containerHeight, onTopPanelHeightChange, topPanelId] ); // This effect will update the panel sizes based on the top panel height whenever // it or the container height changes. This allows us to keep the height of the - // top panel panel fixed when the window is resized. + // top panel fixed when the window is resized. useEffect(() => { if (!containerHeight) { return; @@ -109,8 +121,17 @@ export const DiscoverPanelsResizable = ({ mainPanelSize = 100 - topPanelSize; } - setPanelSizes({ topPanelSize, mainPanelSize }); - }, [containerHeight, topPanelHeight, minTopPanelHeight, minMainPanelHeight]); + const newPanelSizes = { + topPanelSize: round(topPanelSize, 4), + mainPanelSize: round(mainPanelSize, 4), + }; + + // Skip updating the panel sizes if they haven't changed + // since onPanelSizeChange will also trigger this effect. + if (!isEqual(panelSizes, newPanelSizes)) { + setPanelSizes(newPanelSizes); + } + }, [containerHeight, minMainPanelHeight, minTopPanelHeight, panelSizes, topPanelHeight]); const onResizeEnd = () => { // We don't want the resize button to retain focus after the resize is complete, @@ -126,19 +147,27 @@ export const DiscoverPanelsResizable = ({ disableResizeWithPortalsHack(); }; + const { euiTheme } = useEuiTheme(); + const buttonCss = css` + && { + margin-top: -${euiTheme.size.base}; + margin-bottom: 0; + } + `; + return (
      {(EuiResizablePanel, EuiResizableButton) => ( <> @@ -147,26 +176,26 @@ export const DiscoverPanelsResizable = ({ minSize={`${minTopPanelHeight}px`} size={panelSizes.topPanelSize} paddingSize="none" - data-test-subj="dscResizablePanelTop" + data-test-subj="unifiedHistogramResizablePanelTop" > {topPanel} {mainPanel} diff --git a/src/plugins/unified_histogram/public/plugin.ts b/src/plugins/unified_histogram/public/plugin.ts new file mode 100644 index 0000000000000..e1503be5f5b09 --- /dev/null +++ b/src/plugins/unified_histogram/public/plugin.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Plugin } from '@kbn/core/public'; + +export class UnifiedHistogramPublicPlugin implements Plugin<{}, {}, object, {}> { + public setup() { + return {}; + } + + public start() { + return {}; + } +} diff --git a/src/plugins/unified_histogram/public/types.ts b/src/plugins/unified_histogram/public/types.ts new file mode 100644 index 0000000000000..53f81b0819900 --- /dev/null +++ b/src/plugins/unified_histogram/public/types.ts @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Theme } from '@kbn/charts-plugin/public/plugin'; +import type { IUiSettingsClient } from '@kbn/core/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { Duration, Moment } from 'moment'; +import type { Unit } from '@kbn/datemath'; +import type { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; + +/** + * The fetch status of a unified histogram request + */ +export type UnifiedHistogramFetchStatus = + | 'uninitialized' + | 'loading' + | 'partial' + | 'complete' + | 'error'; + +/** + * The services required by the unified histogram components + */ +export interface UnifiedHistogramServices { + data: DataPublicPluginStart; + theme: Theme; + uiSettings: IUiSettingsClient; + fieldFormats: FieldFormatsStart; +} + +interface Column { + id: string; + name: string; +} + +interface Row { + [key: string]: number | 'NaN'; +} + +interface Dimension { + accessor: 0 | 1; + format: SerializedFieldFormat<{ pattern: string }>; + label: string; +} + +interface Ordered { + date: true; + interval: Duration; + intervalESUnit: string; + intervalESValue: number; + min: Moment; + max: Moment; +} + +interface HistogramParams { + date: true; + interval: Duration; + intervalESValue: number; + intervalESUnit: Unit; + format: string; + bounds: HistogramParamsBounds; +} + +export interface HistogramParamsBounds { + min: Moment; + max: Moment; +} + +export interface Table { + columns: Column[]; + rows: Row[]; +} + +export interface Dimensions { + x: Dimension & { params: HistogramParams }; + y: Dimension; +} + +/** + * The chartData object returned by {@link buildChartData} that + * should be used to set {@link UnifiedHistogramChartContext.data} + */ +export interface UnifiedHistogramChartData { + values: Array<{ + x: number; + y: number; + }>; + xAxisOrderedValues: number[]; + xAxisFormat: Dimension['format']; + yAxisFormat: Dimension['format']; + xAxisLabel: Column['name']; + yAxisLabel?: Column['name']; + ordered: Ordered; +} + +/** + * The bucketInterval object returned by {@link buildChartData} that + * should be used to set {@link UnifiedHistogramChartContext.bucketInterval} + */ +export interface UnifiedHistogramBucketInterval { + scaled?: boolean; + description?: string; + scale?: number; +} + +/** + * Context object for the hits count + */ +export interface UnifiedHistogramHitsContext { + /** + * The fetch status of the hits count request + */ + status: UnifiedHistogramFetchStatus; + /** + * The total number of hits + */ + total?: number; +} + +/** + * Context object for the chart + */ +export interface UnifiedHistogramChartContext { + /** + * The fetch status of the chart request + */ + status: UnifiedHistogramFetchStatus; + /** + * Controls whether or not the chart is hidden + */ + hidden?: boolean; + /** + * Controls the time interval of the chart + */ + timeInterval?: string; + /** + * The bucketInterval object returned by {@link buildChartData} + */ + bucketInterval?: UnifiedHistogramBucketInterval; + /** + * The chartData object returned by {@link buildChartData} + */ + data?: UnifiedHistogramChartData; + /** + * Error from failed chart request + */ + error?: Error; +} diff --git a/src/plugins/unified_histogram/tsconfig.json b/src/plugins/unified_histogram/tsconfig.json new file mode 100644 index 0000000000000..af8f24161fd31 --- /dev/null +++ b/src/plugins/unified_histogram/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": ["common/**/*", "public/**/*", "server/**/*"], + "references": [ + { "path": "../../core/tsconfig.json" }, + { "path": "../charts/tsconfig.json" }, + { "path": "../data/tsconfig.json" }, + { "path": "../data_views/tsconfig.json" }, + { "path": "../saved_search/tsconfig.json" } + ] +} diff --git a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx index 40d3abfb7fae0..60e0659a6112a 100644 --- a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx +++ b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx @@ -22,7 +22,7 @@ const mockIndexPatterns = [ title: 'logstash-*', fields: [ { - name: 'response', + name: 'bytes', type: 'number', esTypes: ['integer'], aggregatable: true, @@ -30,6 +30,7 @@ const mockIndexPatterns = [ searchable: true, }, ], + getName: () => 'logstash-*', }, { id: '1235', @@ -44,6 +45,7 @@ const mockIndexPatterns = [ searchable: true, }, ], + getName: () => 'test-*', }, ] as DataView[]; @@ -162,6 +164,11 @@ const services = { ], }, }, + dataViewEditor: { + userPermissions: { + editDataView: action('editDataView'), + }, + }, }; setIndexPatterns({ @@ -173,7 +180,6 @@ function wrapSearchBarInContext(testProps: SearchBarProps) { appName: 'test', timeHistory: mockTimeHistory, intl: null as any, - showQueryBar: true, showFilterBar: true, showDatePicker: true, showAutoRefreshOnly: false, diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx index 27a1d9db7739d..4ba3bf693cf54 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx @@ -37,12 +37,13 @@ export function isRangeParams(params: any): params is RangeParams { function RangeValueInputUI(props: Props) { const kibana = useKibana(); - const tzConfig = kibana.services.uiSettings!.get('dateFormat:tz'); const formatDateChange = (value: string | number | boolean) => { if (typeof value !== 'string' && typeof value !== 'number') return value; - const momentParsedValue = moment(value).tz(tzConfig); + const tzConfig = kibana.services.uiSettings!.get('dateFormat:tz'); + const tz = !tzConfig || tzConfig === 'Browser' ? moment.tz.guess() : tzConfig; + const momentParsedValue = moment(value).tz(tz); if (momentParsedValue.isValid()) return momentParsedValue?.format('YYYY-MM-DDTHH:mm:ss.SSSZ'); return value; diff --git a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx index 5c0dfda5d9b2c..35555137f12b2 100644 --- a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx @@ -190,7 +190,6 @@ export function createSearchBar({ showAutoRefreshOnly={props.showAutoRefreshOnly} showDatePicker={props.showDatePicker} showFilterBar={props.showFilterBar} - showQueryBar={props.showQueryBar} showQueryInput={props.showQueryInput} showSaveQuery={props.showSaveQuery} showSubmitButton={props.showSubmitButton} diff --git a/src/plugins/unified_search/public/search_bar/search_bar.test.tsx b/src/plugins/unified_search/public/search_bar/search_bar.test.tsx index 518f9d1f16e16..0d0ff97ae4b05 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.test.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.test.tsx @@ -211,7 +211,6 @@ describe('SearchBar', () => { screenTitle: 'test screen', onQuerySubmit: noop, query: kqlQuery, - showQueryBar: false, showQueryInput: false, }) ); diff --git a/src/plugins/unified_search/public/search_bar/search_bar.tsx b/src/plugins/unified_search/public/search_bar/search_bar.tsx index 76746d8a86979..ebaa3a317c270 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.tsx @@ -48,7 +48,6 @@ export interface SearchBarOwnProps { screenTitle?: string; dataTestSubj?: string; // Togglers - showQueryBar?: boolean; showQueryInput?: boolean; showFilterBar?: boolean; showDatePicker?: boolean; @@ -122,7 +121,6 @@ class SearchBarUI extends C State > { public static defaultProps = { - showQueryBar: true, showFilterBar: true, showDatePicker: true, showSubmitButton: true, diff --git a/src/plugins/vis_type_markdown/public/markdown_vis.ts b/src/plugins/vis_type_markdown/public/markdown_vis.ts index a4b4010064e78..33acfa21cd0b0 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis.ts +++ b/src/plugins/vis_type_markdown/public/markdown_vis.ts @@ -58,7 +58,6 @@ export const markdownVisDefinition: VisTypeDefinition = { options: { showTimePicker: false, showFilterBar: false, - showQueryBar: true, showQueryInput: false, }, inspectorAdapters: {}, diff --git a/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts b/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts index 55a8aaa218837..6a33feb853221 100644 --- a/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts +++ b/src/plugins/vis_types/heatmap/public/sample_vis.test.mocks.ts @@ -14,7 +14,6 @@ export const sampleAreaVis = { stage: 'production', options: { showTimePicker: true, - showQueryBar: true, showFilterBar: true, showIndexSelection: true, hierarchicalData: false, diff --git a/src/plugins/vis_types/pie/public/sample_vis.test.mocks.ts b/src/plugins/vis_types/pie/public/sample_vis.test.mocks.ts index 035432de9ad23..58a512d95bd64 100644 --- a/src/plugins/vis_types/pie/public/sample_vis.test.mocks.ts +++ b/src/plugins/vis_types/pie/public/sample_vis.test.mocks.ts @@ -20,7 +20,6 @@ export const samplePieVis = { stage: 'production', options: { showTimePicker: true, - showQueryBar: true, showFilterBar: true, showIndexSelection: true, hierarchicalData: false, diff --git a/src/plugins/vis_types/timelion/public/components/timelion_vis_component.tsx b/src/plugins/vis_types/timelion/public/components/timelion_vis_component.tsx index 9e99b2e96d78d..9d59cf105af66 100644 --- a/src/plugins/vis_types/timelion/public/components/timelion_vis_component.tsx +++ b/src/plugins/vis_types/timelion/public/components/timelion_vis_component.tsx @@ -59,6 +59,7 @@ interface TimelionVisComponentProps { renderComplete: IInterpreterRenderHandlers['done']; ariaLabel?: string; syncTooltips?: boolean; + syncCursor?: boolean; } const DefaultYAxis = () => ( @@ -104,6 +105,7 @@ export const TimelionVisComponent = ({ onBrushEvent, ariaLabel, syncTooltips, + syncCursor, }: TimelionVisComponentProps) => { const kibana = useKibana(); const chartRef = useRef(null); @@ -203,7 +205,7 @@ export const TimelionVisComponent = ({ showLegendExtra={true} legendPosition={legend.legendPosition} onRenderChange={onRenderChange} - onPointerUpdate={handleCursorUpdate} + onPointerUpdate={syncCursor ? handleCursorUpdate : undefined} externalPointerEvents={{ tooltip: { visible: syncTooltips, placement: Placement.Right }, }} diff --git a/src/plugins/vis_types/timelion/public/timelion_vis_fn.ts b/src/plugins/vis_types/timelion/public/timelion_vis_fn.ts index 3a268e61690a1..c072f40e42ca9 100644 --- a/src/plugins/vis_types/timelion/public/timelion_vis_fn.ts +++ b/src/plugins/vis_types/timelion/public/timelion_vis_fn.ts @@ -22,6 +22,7 @@ export interface TimelionRenderValue { visType: 'timelion'; visParams: TimelionVisParams; syncTooltips: boolean; + syncCursor: boolean; } export interface TimelionVisParams { @@ -75,6 +76,7 @@ export const getTimelionVisualizationConfig = ( variables, abortSignal: expressionAbortSignal, isSyncTooltipsEnabled, + isSyncCursorEnabled, } ) { const { getTimelionRequestHandler } = await import('./async_services'); @@ -114,6 +116,7 @@ export const getTimelionVisualizationConfig = ( visType: TIMELION_VIS_NAME, visData, syncTooltips: isSyncTooltipsEnabled?.() ?? false, + syncCursor: isSyncTooltipsEnabled?.() ?? true, }, }; }, diff --git a/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx b/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx index ab60f7683dc2d..40541a00c4fcb 100644 --- a/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx +++ b/src/plugins/vis_types/timelion/public/timelion_vis_renderer.tsx @@ -43,7 +43,7 @@ export const getTimelionVisRenderer: ( name: 'timelion_vis', displayName: 'Timelion visualization', reuseDomNode: true, - render: (domNode, { visData, visParams, syncTooltips }, handlers) => { + render: (domNode, { visData, visParams, syncTooltips, syncCursor }, handlers) => { handlers.onDestroy(() => { unmountComponentAtNode(domNode); }); @@ -99,6 +99,7 @@ export const getTimelionVisRenderer: ( renderComplete={renderComplete} onBrushEvent={onBrushEvent} syncTooltips={syncTooltips} + syncCursor={syncCursor} /> )} diff --git a/src/plugins/vis_types/timelion/public/timelion_vis_type.tsx b/src/plugins/vis_types/timelion/public/timelion_vis_type.tsx index f8d7415f6aefe..011f6f6aafeee 100644 --- a/src/plugins/vis_types/timelion/public/timelion_vis_type.tsx +++ b/src/plugins/vis_types/timelion/public/timelion_vis_type.tsx @@ -66,7 +66,6 @@ export function getTimelionVisDefinition(dependencies: TimelionVisDependencies) }, options: { showIndexSelection: false, - showQueryBar: true, showFilterBar: false, showQueryInput: false, }, diff --git a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx index ca374d667463d..bb3d8122c9609 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/timeseries_visualization.tsx @@ -37,6 +37,7 @@ interface TimeseriesVisualizationProps { visData: TimeseriesVisData; uiState: PersistedState; syncColors: boolean; + syncCursor: boolean; syncTooltips: boolean; initialRender: () => void; } @@ -48,6 +49,7 @@ function TimeseriesVisualization({ uiState, getConfig, syncColors, + syncCursor, syncTooltips, initialRender, }: TimeseriesVisualizationProps) { @@ -194,6 +196,7 @@ function TimeseriesVisualization({ onUiState={handleUiState} syncColors={syncColors} syncTooltips={syncTooltips} + syncCursor={syncCursor} palettesService={palettesService} indexPattern={indexPattern} fieldFormatMap={indexPattern?.fieldFormatMap} diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts b/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts index b7fee33728314..65f8dfa763093 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/index.ts @@ -64,6 +64,7 @@ export interface TimeseriesVisProps { getConfig: IUiSettingsClient['get']; syncColors: boolean; syncTooltips: boolean; + syncCursor: boolean; palettesService: PaletteRegistry; indexPattern?: FetchedIndexPattern['indexPattern']; /** @deprecated please use indexPattern.fieldFormatMap instead **/ diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js index 25d64816614a9..411bb9e41b5e4 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/timeseries/vis.js @@ -163,6 +163,7 @@ class TimeseriesVisualization extends Component { onFilterClick, syncColors, syncTooltips, + syncCursor, palettesService, fieldFormatMap, getConfig, @@ -275,6 +276,7 @@ class TimeseriesVisualization extends Component { annotations={this.prepareAnnotations()} syncColors={syncColors} syncTooltips={syncTooltips} + syncCursor={syncCursor} palettesService={palettesService} interval={interval} initialRender={initialRender} diff --git a/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js b/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js index e075cac92641c..1ca0f6d50efcc 100644 --- a/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js +++ b/src/plugins/vis_types/timeseries/public/application/visualizations/views/timeseries/index.js @@ -73,6 +73,7 @@ export const TimeSeries = ({ annotations, syncColors, syncTooltips, + syncCursor, palettesService, interval, isLastBucketDropped, @@ -179,7 +180,7 @@ export const TimeSeries = ({ onBrushEnd={onBrushEndListener} onElementClick={(args) => handleElementClick(args)} animateData={false} - onPointerUpdate={handleCursorUpdate} + onPointerUpdate={syncCursor ? handleCursorUpdate : undefined} pointerUpdateDebounce={0} theme={[ { diff --git a/src/plugins/vis_types/timeseries/public/metrics_fn.ts b/src/plugins/vis_types/timeseries/public/metrics_fn.ts index e6e2814b6e08b..fe9406895cd6e 100644 --- a/src/plugins/vis_types/timeseries/public/metrics_fn.ts +++ b/src/plugins/vis_types/timeseries/public/metrics_fn.ts @@ -26,6 +26,7 @@ export interface TimeseriesRenderValue { visData: TimeseriesVisData | {}; visParams: TimeseriesVisParams; syncColors: boolean; + syncCursor: boolean; syncTooltips: boolean; canNavigateToLens?: boolean; } @@ -63,6 +64,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ getSearchSessionId, isSyncColorsEnabled, isSyncTooltipsEnabled, + isSyncCursorEnabled, getExecutionContext, inspectorAdapters, abortSignal: expressionAbortSignal, @@ -73,6 +75,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ const uiState = JSON.parse(args.uiState); const syncColors = isSyncColorsEnabled?.() ?? false; const syncTooltips = isSyncTooltipsEnabled?.() ?? false; + const syncCursor = isSyncCursorEnabled?.() ?? true; const response = await metricsRequestHandler({ input, @@ -92,6 +95,7 @@ export const createMetricsFn = (): TimeseriesExpressionFunctionDefinition => ({ visData: response, syncColors, syncTooltips, + syncCursor, canNavigateToLens: variables.canNavigateToLens as boolean, }, }; diff --git a/src/plugins/vis_types/timeseries/public/metrics_type.ts b/src/plugins/vis_types/timeseries/public/metrics_type.ts index 2e18e9c0af48e..3bf9f9b90bf1a 100644 --- a/src/plugins/vis_types/timeseries/public/metrics_type.ts +++ b/src/plugins/vis_types/timeseries/public/metrics_type.ts @@ -157,7 +157,6 @@ export const metricsVisDefinition: VisTypeDefinition< editor: TSVB_EDITOR_NAME, }, options: { - showQueryBar: true, showFilterBar: true, showIndexSelection: false, }, diff --git a/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx b/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx index 4d64e46356c0d..065259ce8882c 100644 --- a/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx +++ b/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx @@ -62,7 +62,14 @@ export const getTimeseriesVisRenderer: (deps: { handlers.onDestroy(() => { unmountComponentAtNode(domNode); }); - const { visParams: model, visData, syncColors, syncTooltips, canNavigateToLens } = config; + const { + visParams: model, + visData, + syncColors, + syncTooltips, + syncCursor, + canNavigateToLens, + } = config; const showNoResult = !checkIfDataExists(visData, model); const renderComplete = () => { @@ -106,6 +113,7 @@ export const getTimeseriesVisRenderer: (deps: { visData={visData as TimeseriesVisData} syncColors={syncColors} syncTooltips={syncTooltips} + syncCursor={syncCursor} uiState={handlers.uiState! as PersistedState} initialRender={renderComplete} /> diff --git a/src/plugins/vis_types/vega/public/vega_type.ts b/src/plugins/vis_types/vega/public/vega_type.ts index 798930db1f975..3299c86dc0a80 100644 --- a/src/plugins/vis_types/vega/public/vega_type.ts +++ b/src/plugins/vis_types/vega/public/vega_type.ts @@ -51,7 +51,6 @@ export const createVegaTypeDefinition = (): VisTypeDefinition => { toExpressionAst, options: { showIndexSelection: false, - showQueryBar: true, showFilterBar: true, }, getSupportedTriggers: () => { diff --git a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.mocks.ts b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.mocks.ts index 0f6f403d16ac8..a60e6577d412a 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.mocks.ts +++ b/src/plugins/vis_types/xy/public/editor/components/options/point_series/point_series.mocks.ts @@ -346,7 +346,6 @@ export const getVis = (bucketType: string) => { titleInWizard: '', options: { showTimePicker: true, - showQueryBar: true, showFilterBar: true, showIndexSelection: true, hierarchicalData: false, diff --git a/src/plugins/vis_types/xy/public/sample_vis.test.mocks.ts b/src/plugins/vis_types/xy/public/sample_vis.test.mocks.ts index b2660b7c66551..da78864bc08d0 100644 --- a/src/plugins/vis_types/xy/public/sample_vis.test.mocks.ts +++ b/src/plugins/vis_types/xy/public/sample_vis.test.mocks.ts @@ -19,7 +19,6 @@ export const sampleAreaVis = { stage: 'production', options: { showTimePicker: true, - showQueryBar: true, showFilterBar: true, showIndexSelection: true, hierarchicalData: false, diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx index 26746f8d23200..ef9e8d53a4f11 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.tsx @@ -110,6 +110,7 @@ export class VisualizeEmbeddable private searchSessionId?: string; private syncColors?: boolean; private syncTooltips?: boolean; + private syncCursor?: boolean; private embeddableTitle?: string; private visCustomizations?: Pick; private subscriptions: Subscription[] = []; @@ -154,6 +155,7 @@ export class VisualizeEmbeddable this.timefilter = timefilter; this.syncColors = this.input.syncColors; this.syncTooltips = this.input.syncTooltips; + this.syncCursor = this.input.syncCursor; this.searchSessionId = this.input.searchSessionId; this.query = this.input.query; this.embeddableTitle = this.getTitle(); @@ -322,6 +324,11 @@ export class VisualizeEmbeddable dirty = true; } + if (this.syncCursor !== this.input.syncCursor) { + this.syncCursor = this.input.syncCursor; + dirty = true; + } + if (this.embeddableTitle !== this.getTitle()) { this.embeddableTitle = this.getTitle(); dirty = true; @@ -574,6 +581,7 @@ export class VisualizeEmbeddable searchSessionId: this.input.searchSessionId, syncColors: this.input.syncColors, syncTooltips: this.input.syncTooltips, + syncCursor: this.input.syncCursor, uiState: this.vis.uiState, interactive: !this.input.disableTriggers, inspectorAdapters: this.inspectorAdapters, diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 2d351f18a3b47..4253b134cb748 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -15,7 +15,6 @@ import { Schemas } from './schemas'; const defaultOptions: VisTypeOptions = { showTimePicker: true, - showQueryBar: true, showFilterBar: true, showIndexSelection: true, showQueryInput: true, diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index 9689729f187fd..5d581a52130a5 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -22,7 +22,6 @@ import { NavigateToLensContext } from '../../common'; export interface VisTypeOptions { showTimePicker: boolean; - showQueryBar: boolean; showFilterBar: boolean; showIndexSelection: boolean; showQueryInput: boolean; diff --git a/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx b/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx index 055b326b8f19f..e7512c6dd6473 100644 --- a/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx +++ b/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx @@ -170,8 +170,7 @@ const TopNav = ({ return vis.type.options.showTimePicker && hasTimeField; }; const showFilterBar = vis.type.options.showFilterBar; - const showQueryInput = - vis.type.requiresSearch && vis.type.options.showQueryBar && vis.type.options.showQueryInput; + const showQueryInput = vis.type.requiresSearch && vis.type.options.showQueryInput; useEffect(() => { return () => { diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index 841724347c004..face35f4e6730 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -144,23 +144,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('a11y test for chart options panel', async () => { - await testSubjects.click('discoverChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); await a11y.testAppSnapshot(); }); it('a11y test for data grid with hidden chart', async () => { - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); await a11y.testAppSnapshot(); - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); }); it('a11y test for time interval panel', async () => { - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverTimeIntervalPanel'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramTimeIntervalPanel'); await a11y.testAppSnapshot(); await testSubjects.click('contextMenuPanelTitleButton'); - await testSubjects.click('discoverChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); }); it('a11y test for data grid sort panel', async () => { diff --git a/test/examples/search/warnings.ts b/test/examples/search/warnings.ts index fc1949549d66e..2cc674fb01024 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -159,7 +159,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { toasts = await find.allByCssSelector(toastsSelector); expect(toasts.length).to.be(2); }); - const expects = ['2 of 4 shards failed', 'Query result']; + const expects = ['Query result', '2 of 4 shards failed']; await asyncForEach(toasts, async (t, index) => { expect(await t.getVisibleText()).to.eql(expects[index]); }); diff --git a/test/functional/apps/dashboard/group6/share.ts b/test/functional/apps/dashboard/group6/share.ts index 871ab5bed1488..40cea873988e1 100644 --- a/test/functional/apps/dashboard/group6/share.ts +++ b/test/functional/apps/dashboard/group6/share.ts @@ -9,11 +9,94 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +type TestingModes = 'snapshot' | 'savedObject'; +type AppState = string | undefined; +interface UrlState { + globalState: string; + appState: AppState; +} + +const getStateFromUrl = (url: string): UrlState => { + const globalStateStart = url.indexOf('_g'); + const appStateStart = url.indexOf('_a'); + + // global state is always part of the URL, but app state is *not* - so, need to + // modify the logic depending on whether app state exists or not + if (appStateStart === -1) { + return { + globalState: url.substring(globalStateStart + 3), + appState: undefined, + }; + } + return { + globalState: url.substring(globalStateStart + 3, appStateStart - 1), + appState: url.substring(appStateStart + 3, url.length), + }; +}; + export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const filterBar = getService('filterBar'); const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['dashboard', 'common', 'share']); + const testSubjects = getService('testSubjects'); + const dashboardPanelActions = getService('dashboardPanelActions'); + + const PageObjects = getPageObjects(['dashboard', 'common', 'share', 'timePicker']); + + const getSharedUrl = async (mode: TestingModes): Promise => { + await retry.waitFor('share menu to open', async () => { + await PageObjects.share.clickShareTopNavButton(); + return await PageObjects.share.isShareMenuOpen(); + }); + if (mode === 'savedObject') { + await PageObjects.share.exportAsSavedObject(); + } + const sharedUrl = await PageObjects.share.getSharedUrl(); + return sharedUrl; + }; describe('share dashboard', () => { + const testFilterState = async (mode: TestingModes) => { + it('should not have "filters" state in either app or global state when no filters', async () => { + expect(await getSharedUrl(mode)).to.not.contain('filters'); + }); + + it('unpinned filter should show up only in app state when dashboard is unsaved', async () => { + await filterBar.addFilter('geo.src', 'is', 'AE'); + await PageObjects.dashboard.waitForRenderComplete(); + + const sharedUrl = await getSharedUrl(mode); + const { globalState, appState } = getStateFromUrl(sharedUrl); + expect(globalState).to.not.contain('filters'); + if (mode === 'snapshot') { + expect(appState).to.contain('filters'); + } else { + expect(sharedUrl).to.not.contain('appState'); + } + }); + + it('unpinned filters should be removed from app state when dashboard is saved', async () => { + await PageObjects.dashboard.clickQuickSave(); + await PageObjects.dashboard.waitForRenderComplete(); + + const sharedUrl = await getSharedUrl(mode); + expect(sharedUrl).to.not.contain('appState'); + }); + + it('pinned filter should show up only in global state', async () => { + await filterBar.toggleFilterPinned('geo.src'); + await PageObjects.dashboard.clickQuickSave(); + await PageObjects.dashboard.waitForRenderComplete(); + + const sharedUrl = await getSharedUrl(mode); + const { globalState, appState } = getStateFromUrl(sharedUrl); + expect(globalState).to.contain('filters'); + if (mode === 'snapshot') { + expect(appState).to.not.contain('filters'); + } + }); + }; + before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await kibanaServer.importExport.load( @@ -25,16 +108,58 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.preserveCrossAppState(); await PageObjects.dashboard.loadSavedDashboard('few panels'); + + await PageObjects.dashboard.switchToEditMode(); + const from = 'Sep 19, 2017 @ 06:31:44.000'; + const to = 'Sep 23, 2018 @ 18:31:44.000'; + await PageObjects.timePicker.setAbsoluteRange(from, to); + await PageObjects.dashboard.waitForRenderComplete(); }); after(async () => { await kibanaServer.savedObjects.cleanStandardList(); }); - it('has "panels" state when sharing a snapshot', async () => { - await PageObjects.share.clickShareTopNavButton(); - const sharedUrl = await PageObjects.share.getSharedUrl(); - expect(sharedUrl).to.contain('panels'); + describe('snapshot share', async () => { + describe('test local state', async () => { + it('should not have "panels" state when not in unsaved changes state', async () => { + await testSubjects.missingOrFail('dashboardUnsavedChangesBadge'); + expect(await getSharedUrl('snapshot')).to.not.contain('panels'); + }); + + it('should have "panels" in app state when a panel has been modified', async () => { + await dashboardPanelActions.setCustomPanelTitle('Test New Title'); + await PageObjects.dashboard.waitForRenderComplete(); + await testSubjects.existOrFail('dashboardUnsavedChangesBadge'); + + const sharedUrl = await getSharedUrl('snapshot'); + const { appState } = getStateFromUrl(sharedUrl); + expect(appState).to.contain('panels'); + }); + + it('should once again not have "panels" state when save is clicked', async () => { + await PageObjects.dashboard.clickQuickSave(); + await PageObjects.dashboard.waitForRenderComplete(); + await testSubjects.missingOrFail('dashboardUnsavedChangesBadge'); + expect(await getSharedUrl('snapshot')).to.not.contain('panels'); + }); + }); + + describe('test filter state', async () => { + await testFilterState('snapshot'); + }); + + after(async () => { + await filterBar.removeAllFilters(); + await PageObjects.dashboard.clickQuickSave(); + await PageObjects.dashboard.waitForRenderComplete(); + }); + }); + + describe('saved object share', async () => { + describe('test filter state', async () => { + await testFilterState('savedObject'); + }); }); }); } diff --git a/test/functional/apps/discover/group1/_discover.ts b/test/functional/apps/discover/group1/_discover.ts index 1ac0ad6fe013f..d6035d0a28a6e 100644 --- a/test/functional/apps/discover/group1/_discover.ts +++ b/test/functional/apps/discover/group1/_discover.ts @@ -347,9 +347,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('resizable layout panels', () => { it('should allow resizing the layout panels', async () => { const resizeDistance = 100; - const topPanel = await testSubjects.find('dscResizablePanelTop'); - const mainPanel = await testSubjects.find('dscResizablePanelMain'); - const resizeButton = await testSubjects.find('dsc-resizable-button'); + const topPanel = await testSubjects.find('unifiedHistogramResizablePanelTop'); + const mainPanel = await testSubjects.find('unifiedHistogramResizablePanelMain'); + const resizeButton = await testSubjects.find('unifiedHistogramResizableButton'); const topPanelSize = (await topPanel.getPosition()).height; const mainPanelSize = (await mainPanel.getPosition()).height; await browser.dragAndDrop( diff --git a/test/functional/apps/discover/group1/_discover_histogram.ts b/test/functional/apps/discover/group1/_discover_histogram.ts index 5257b5edbe235..12effb75cb7f3 100644 --- a/test/functional/apps/discover/group1/_discover_histogram.ts +++ b/test/functional/apps/discover/group1/_discover_histogram.ts @@ -81,16 +81,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await prepareTest({ from, to }); let canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(true); - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(false); // histogram is hidden, when reloading the page it should remain hidden await browser.refresh(); canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(false); - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); await PageObjects.header.waitUntilLoadingHasFinished(); canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(true); @@ -102,8 +102,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await prepareTest({ from, to }); // close chart for saved search - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); let canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(false); @@ -122,8 +122,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(false); // open chart for saved search - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); await retry.waitFor(`Discover histogram to be displayed`, async () => { canvasExists = await elasticChart.canvasExists(); return canvasExists; @@ -145,8 +145,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should show permitted hidden histogram state when returning back to discover', async () => { // close chart - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); let canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(false); @@ -155,8 +155,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.header.waitUntilLoadingHasFinished(); // open chart - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(true); @@ -171,8 +171,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(true); // close chart - await testSubjects.click('discoverChartOptionsToggle'); - await testSubjects.click('discoverChartToggle'); + await testSubjects.click('unifiedHistogramChartOptionsToggle'); + await testSubjects.click('unifiedHistogramChartToggle'); canvasExists = await elasticChart.canvasExists(); expect(canvasExists).to.be(false); }); diff --git a/test/functional/apps/discover/group2/_sql_view.ts b/test/functional/apps/discover/group2/_sql_view.ts index d8ec69db66ee4..325752bc39fad 100644 --- a/test/functional/apps/discover/group2/_sql_view.ts +++ b/test/functional/apps/discover/group2/_sql_view.ts @@ -43,8 +43,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await testSubjects.exists('superDatePickerToggleQuickMenuButton')).to.be(true); expect(await testSubjects.exists('addFilter')).to.be(true); expect(await testSubjects.exists('dscViewModeDocumentButton')).to.be(true); - expect(await testSubjects.exists('discoverChart')).to.be(true); - expect(await testSubjects.exists('discoverQueryHits')).to.be(true); + expect(await testSubjects.exists('unifiedHistogramChart')).to.be(true); + expect(await testSubjects.exists('unifiedHistogramQueryHits')).to.be(true); expect(await testSubjects.exists('discoverAlertsButton')).to.be(true); expect(await testSubjects.exists('shareTopNavButton')).to.be(true); expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(true); @@ -64,8 +64,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await testSubjects.exists('showQueryBarMenu')).to.be(false); expect(await testSubjects.exists('addFilter')).to.be(false); expect(await testSubjects.exists('dscViewModeDocumentButton')).to.be(false); - expect(await testSubjects.exists('discoverChart')).to.be(false); - expect(await testSubjects.exists('discoverQueryHits')).to.be(false); + expect(await testSubjects.exists('unifiedHistogramChart')).to.be(false); + expect(await testSubjects.exists('unifiedHistogramQueryHits')).to.be(false); expect(await testSubjects.exists('discoverAlertsButton')).to.be(false); expect(await testSubjects.exists('shareTopNavButton')).to.be(false); expect(await testSubjects.exists('docTableExpandToggleColumn')).to.be(false); diff --git a/test/functional/apps/management/_index_pattern_create_delete.ts b/test/functional/apps/management/_index_pattern_create_delete.ts index 398489d415c70..e9ceba4439a03 100644 --- a/test/functional/apps/management/_index_pattern_create_delete.ts +++ b/test/functional/apps/management/_index_pattern_create_delete.ts @@ -128,6 +128,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); }); + it('can save with same name', async () => { + await PageObjects.settings.editIndexPattern( + 'logstash-*,hello_world*', + '@timestamp', + 'Logstash Star', + true + ); + + await retry.try(async () => { + expect(await testSubjects.getVisibleText('indexPatternTitle')).to.contain( + `Logstash Star` + ); + }); + }); it('shows edit confirm message when editing index-pattern', async () => { await PageObjects.settings.editIndexPattern( 'logstash-2*', diff --git a/test/functional/apps/visualize/group5/_tsvb_time_series.ts b/test/functional/apps/visualize/group5/_tsvb_time_series.ts index f9e016ff1f635..fb59d947b6790 100644 --- a/test/functional/apps/visualize/group5/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/group5/_tsvb_time_series.ts @@ -11,11 +11,12 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { visualize, visualBuilder, timeToVisualize, dashboard, common } = getPageObjects([ + const { visualize, visualBuilder, timeToVisualize, dashboard, header, common } = getPageObjects([ 'visualBuilder', 'visualize', 'timeToVisualize', 'dashboard', + 'header', 'common', ]); const security = getService('security'); @@ -221,6 +222,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should create a filter for series with multiple split by terms fields one of which has formatting', async () => { const expectedFilterPills = ['0, win 7']; await visualBuilder.setMetricsGroupByTerms('bytes'); + await header.waitUntilLoadingHasFinished(); await visualBuilder.setAnotherGroupByTermsField('machine.os.raw'); await visualBuilder.clickSeriesOption(); await visualBuilder.setChartType('Bar'); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index d9bc8c46a4acc..85c93c0fc2847 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -29,7 +29,7 @@ export class DiscoverPageObject extends FtrService { private readonly defaultFindTimeout = this.config.get('timeouts.find'); public async getChartTimespan() { - return await this.testSubjects.getAttribute('discoverChart', 'data-time-range'); + return await this.testSubjects.getAttribute('unifiedHistogramChart', 'data-time-range'); } public async getDocTable() { @@ -207,40 +207,40 @@ export class DiscoverPageObject extends FtrService { } public async isChartVisible() { - return await this.testSubjects.exists('discoverChart'); + return await this.testSubjects.exists('unifiedHistogramChart'); } public async toggleChartVisibility() { - await this.testSubjects.moveMouseTo('discoverChartOptionsToggle'); - await this.testSubjects.click('discoverChartOptionsToggle'); - await this.testSubjects.exists('discoverChartToggle'); - await this.testSubjects.click('discoverChartToggle'); + await this.testSubjects.moveMouseTo('unifiedHistogramChartOptionsToggle'); + await this.testSubjects.click('unifiedHistogramChartOptionsToggle'); + await this.testSubjects.exists('unifiedHistogramChartToggle'); + await this.testSubjects.click('unifiedHistogramChartToggle'); await this.header.waitUntilLoadingHasFinished(); } public async getChartInterval() { - await this.testSubjects.click('discoverChartOptionsToggle'); - await this.testSubjects.click('discoverTimeIntervalPanel'); - const selectedOption = await this.find.byCssSelector(`.discoverIntervalSelected`); + await this.testSubjects.click('unifiedHistogramChartOptionsToggle'); + await this.testSubjects.click('unifiedHistogramTimeIntervalPanel'); + const selectedOption = await this.find.byCssSelector(`.unifiedHistogramIntervalSelected`); return selectedOption.getVisibleText(); } public async getChartIntervalWarningIcon() { - await this.testSubjects.click('discoverChartOptionsToggle'); + await this.testSubjects.click('unifiedHistogramChartOptionsToggle'); await this.header.waitUntilLoadingHasFinished(); return await this.find.existsByCssSelector('.euiToolTipAnchor'); } public async setChartInterval(interval: string) { - await this.testSubjects.click('discoverChartOptionsToggle'); - await this.testSubjects.click('discoverTimeIntervalPanel'); - await this.testSubjects.click(`discoverTimeInterval-${interval}`); + await this.testSubjects.click('unifiedHistogramChartOptionsToggle'); + await this.testSubjects.click('unifiedHistogramTimeIntervalPanel'); + await this.testSubjects.click(`unifiedHistogramTimeInterval-${interval}`); return await this.header.waitUntilLoadingHasFinished(); } public async getHitCount() { await this.header.waitUntilLoadingHasFinished(); - return await this.testSubjects.getVisibleText('discoverQueryHits'); + return await this.testSubjects.getVisibleText('unifiedHistogramQueryHits'); } public async getDocHeader() { @@ -573,7 +573,7 @@ export class DiscoverPageObject extends FtrService { } public async waitForChartLoadingComplete(renderCount: number) { - await this.elasticChart.waitForRenderingCount(renderCount, 'discoverChart'); + await this.elasticChart.waitForRenderingCount(renderCount, 'unifiedHistogramChart'); } public async waitForDocTableLoadingComplete() { diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 2bfd0c7b5dda3..6509d9149b99d 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -170,12 +170,16 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.cloud.base_url (string)', 'xpack.cloud.cname (string)', 'xpack.cloud.deployment_url (string)', + 'xpack.cloud.is_elastic_staff_owned (boolean)', + 'xpack.cloud.trial_end_date (string)', 'xpack.cloud_integrations.chat.chatURL (string)', // No PII. This is an escape patch to override LaunchDarkly's flag resolution mechanism for testing or quick fix. 'xpack.cloud_integrations.experiments.flag_overrides (record)', // Commented because it's inside a schema conditional, and the test is not able to resolve it. But it's shared. // Added here for documentation purposes. // 'xpack.cloud_integrations.experiments.launch_darkly.client_id (string)', + // 'xpack.cloud_integrations.experiments.launch_darkly.client_log_level (string)', + 'xpack.cloud_integrations.experiments.metadata_refresh_interval (duration)', 'xpack.cloud_integrations.full_story.org_id (any)', // No PII. Just the list of event types we want to forward to FullStory. 'xpack.cloud_integrations.full_story.eventTypesAllowlist (array)', @@ -219,7 +223,10 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.trigger_actions_ui.enableGeoTrackingThresholdAlert (boolean)', 'xpack.upgrade_assistant.readonly (boolean)', 'xpack.upgrade_assistant.ui.enabled (boolean)', - 'xpack.observability.unsafe.alertDetails.enabled (boolean)', + 'xpack.observability.unsafe.alertDetails.apm.enabled (boolean)', + 'xpack.observability.unsafe.alertDetails.metrics.enabled (boolean)', + 'xpack.observability.unsafe.alertDetails.logs.enabled (boolean)', + 'xpack.observability.unsafe.alertDetails.uptime.enabled (boolean)', 'xpack.observability.unsafe.slo.enabled (boolean)', ]; // We don't assert that actualExposedConfigKeys and expectedExposedConfigKeys are equal, because test failure messages with large diff --git a/test/plugin_functional/test_suites/telemetry/telemetry.ts b/test/plugin_functional/test_suites/telemetry/telemetry.ts index 1c68abd5426d3..3b087c2705c10 100644 --- a/test/plugin_functional/test_suites/telemetry/telemetry.ts +++ b/test/plugin_functional/test_suites/telemetry/telemetry.ts @@ -14,8 +14,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const browser = getService('browser'); const PageObjects = getPageObjects(['common']); - // FLAKY: https://github.com/elastic/kibana/issues/107034 - describe.skip('Telemetry service', () => { + describe('Telemetry service', () => { const checkCanSendTelemetry = (): Promise => { return browser.executeAsync((cb) => { (window as unknown as Record Promise>) diff --git a/tsconfig.base.json b/tsconfig.base.json index 3054a36f2bb86..271d6b1dc35df 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -169,6 +169,8 @@ "@kbn/ui-actions-plugin/*": ["src/plugins/ui_actions/*"], "@kbn/unified-field-list-plugin": ["src/plugins/unified_field_list"], "@kbn/unified-field-list-plugin/*": ["src/plugins/unified_field_list/*"], + "@kbn/unified-histogram-plugin": ["src/plugins/unified_histogram"], + "@kbn/unified-histogram-plugin/*": ["src/plugins/unified_histogram/*"], "@kbn/unified-search-plugin": ["src/plugins/unified_search"], "@kbn/unified-search-plugin/*": ["src/plugins/unified_search/*"], "@kbn/url-forwarding-plugin": ["src/plugins/url_forwarding"], diff --git a/x-pack/README.md b/x-pack/README.md index 9c3d0046a77e7..bdbc598aba4dc 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -4,16 +4,33 @@ This directory tree contains files subject to the Elastic License 2.0. The files to the Elastic License 2.0 are grouped in this directory to clearly separate them from files dual-licensed under the Server Side Public License and the Elastic License 2.0. -## Alert Details page (feature flag) +## Alert Details page feature flags (feature-flag-per-App) If you have: ```yaml -xpack.observability.unsafe.alertDetails.enabled: true +xpack.observability.unsafe.alertDetails.apm.enabled: true ``` -In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table +**[For APM rule types]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table +```yaml +xpack.observability.unsafe.alertDetails.metrics.enabled: true +``` + +**[For Infrastructure rule types]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table + +```yaml +xpack.observability.unsafe.alertDetails.logs.enabled: true +``` + +**[For Logs threshold rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table + +```yaml +xpack.observability.unsafe.alertDetails.uptime.enabled: true +``` + +**[For Uptime rule type]** In Kibana configuration, will allow the user to navigate to the new Alert Details page, instead of the Alert Flyout when clicking on `View alert details` in the Alert table # Development @@ -31,15 +48,16 @@ For information on testing, see [the Elastic functional test development guide]( #### Running functional tests -The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.base.js)), *API integration tests* ([specified by this config](test/api_integration/config.ts)), and *SAML API integration tests* ([specified by this config](test/security_api_integration/saml.config.ts)). +The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are _functional UI tests_ ([specified by this config](test/functional/config.base.js)), _API integration tests_ ([specified by this config](test/api_integration/config.ts)), and _SAML API integration tests_ ([specified by this config](test/security_api_integration/saml.config.ts)). The script runs all sets of tests sequentially like so: -* builds Elasticsearch and X-Pack -* runs Elasticsearch with X-Pack -* starts up the Kibana server with X-Pack -* runs the functional UI tests against those servers -* tears down the servers -* repeats the same process for the API and SAML API integration test configs. + +- builds Elasticsearch and X-Pack +- runs Elasticsearch with X-Pack +- starts up the Kibana server with X-Pack +- runs the functional UI tests against those servers +- tears down the servers +- repeats the same process for the API and SAML API integration test configs. To do all of this in a single command run: @@ -100,4 +118,5 @@ yarn test:jest_integration See [here](./test/functional/apps/dashboard/reporting/README.md) for more information on running reporting tests. #### Running Security Solution Cypress E2E/integration tests + See [here](./plugins/security_solution/cypress/README.md) for information on running this test suite. diff --git a/x-pack/plugins/actions/server/lib/action_executor.test.ts b/x-pack/plugins/actions/server/lib/action_executor.test.ts index 54405b03e7c02..35791ffa01f23 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.test.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.test.ts @@ -35,7 +35,9 @@ const executeParams = { }; const spacesMock = spacesServiceMock.createStartContract(); -const loggerMock = loggingSystemMock.create().get(); +const loggerMock: ReturnType = + loggingSystemMock.createLogger(); + const getActionsClientWithRequest = jest.fn(); actionExecutor.initialize({ logger: loggerMock, @@ -52,6 +54,7 @@ beforeEach(() => { jest.resetAllMocks(); spacesMock.getSpaceId.mockReturnValue('some-namespace'); getActionsClientWithRequest.mockResolvedValue(actionsClient); + loggerMock.get.mockImplementation(() => loggerMock); }); test('successfully executes', async () => { @@ -109,6 +112,7 @@ test('successfully executes', async () => { baz: true, }, params: { foo: true }, + logger: loggerMock, }); expect(loggerMock.debug).toBeCalledWith('executing action test:1: 1'); @@ -482,6 +486,7 @@ test('should not throws an error if actionType is preconfigured', async () => { baz: true, }, params: { foo: true }, + logger: loggerMock, }); }); diff --git a/x-pack/plugins/actions/server/lib/action_executor.ts b/x-pack/plugins/actions/server/lib/action_executor.ts index 00a3980833ef2..26d0a55b07dc6 100644 --- a/x-pack/plugins/actions/server/lib/action_executor.ts +++ b/x-pack/plugins/actions/server/lib/action_executor.ts @@ -121,7 +121,6 @@ export class ActionExecutor { }, async (span) => { const { - logger, spaces, getServices, encryptedSavedObjectsClient, @@ -144,6 +143,9 @@ export class ActionExecutor { ); const { actionTypeId, name, config, secrets } = actionInfo; + const loggerId = actionTypeId.startsWith('.') ? actionTypeId.substring(1) : actionTypeId; + let { logger } = this.actionExecutorContext!; + logger = logger.get(loggerId); if (!this.actionInfo || this.actionInfo.actionId !== actionId) { this.actionInfo = actionInfo; @@ -228,6 +230,7 @@ export class ActionExecutor { isEphemeral, taskInfo, configurationUtilities, + logger, }); } catch (err) { if (err.reason === ActionExecutionErrorReason.Validation) { diff --git a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts index 5fc07c4b6f236..92467f049ae3f 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/executor.test.ts @@ -65,6 +65,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }); expect(res).toEqual({ @@ -86,6 +87,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }); expect(res).toEqual({ @@ -107,6 +109,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }); expect(res).toEqual({ @@ -126,6 +129,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }); expect(res).toEqual({ @@ -146,6 +150,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }) ).rejects.toThrowError('You should register at least one subAction for your connector type'); }); @@ -161,6 +166,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }) ).rejects.toThrowError( 'Sub action "not-exist" is not registered. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -178,6 +184,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }) ).rejects.toThrowError( 'Method "not-exist" does not exists in service. Sub action: "testUrl". Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -195,6 +202,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }) ).rejects.toThrowError( 'Method "notAFunction" must be a function. Connector id: test-action-id. Connector name: Test. Connector type: .test' @@ -212,6 +220,7 @@ describe('Executor', () => { secrets, services, configurationUtilities: mockedActionsConfig, + logger, }) ).rejects.toThrowError( 'Request validation failed (Error: [id]: expected value of type [string] but got [undefined])' diff --git a/x-pack/plugins/actions/server/types.ts b/x-pack/plugins/actions/server/types.ts index 3806dae00c237..147a71da0c960 100644 --- a/x-pack/plugins/actions/server/types.ts +++ b/x-pack/plugins/actions/server/types.ts @@ -14,6 +14,7 @@ import { ElasticsearchClient, CustomRequestHandlerContext, SavedObjectReference, + Logger, } from '@kbn/core/server'; import { ActionTypeRegistry } from './action_type_registry'; import { PluginSetupContract, PluginStartContract } from './plugin'; @@ -60,6 +61,7 @@ export interface ActionTypeExecutorOptions { config: Config; secrets: Secrets; params: Params; + logger: Logger; isEphemeral?: boolean; taskInfo?: TaskInfo; configurationUtilities: ActionsConfigurationUtilities; diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index a199fb3b55998..20310fdae01f7 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -202,6 +202,7 @@ describe('Task Runner', () => { alertingEventLogger.getStartAndDuration.mockImplementation(() => ({ start: new Date() })); (AlertingEventLogger as jest.Mock).mockImplementation(() => alertingEventLogger); + logger.get.mockImplementation(() => logger); }); test('successfully executes the task', async () => { diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index 41029af567524..0c6bbfbbd9866 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -136,7 +136,8 @@ export class TaskRunner< inMemoryMetrics: InMemoryMetrics ) { this.context = context; - this.logger = context.logger; + const loggerId = ruleType.id.startsWith('.') ? ruleType.id.substring(1) : ruleType.id; + this.logger = context.logger.get(loggerId); this.usageCounter = context.usageCounter; this.ruleType = ruleType; this.ruleConsumer = null; @@ -392,6 +393,7 @@ export class TaskRunner< throttle, notifyWhen, }, + logger: this.logger, }) ); diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts index 7b920e3957421..92353cb043984 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner_cancel.test.ts @@ -64,6 +64,7 @@ let fakeTimer: sinon.SinonFakeTimers; const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); const alertingEventLogger = alertingEventLoggerMock.create(); +const logger: ReturnType = loggingSystemMock.createLogger(); describe('Task Runner Cancel', () => { let mockedTaskInstance: ConcreteTaskInstance; @@ -110,7 +111,7 @@ describe('Task Runner Cancel', () => { actionsPlugin: actionsMock.createStart(), getRulesClientWithRequest: jest.fn().mockReturnValue(rulesClient), encryptedSavedObjectsClient, - logger: loggingSystemMock.create().get(), + logger, executionContext: executionContextServiceMock.createInternalStartContract(), spaceIdToNamespace: jest.fn().mockReturnValue(undefined), basePathService: httpServiceMock.createBasePath(), @@ -170,6 +171,7 @@ describe('Task Runner Cancel', () => { taskRunnerFactoryInitializerParams.actionsPlugin.isActionExecutable.mockReturnValue(true); alertingEventLogger.getStartAndDuration.mockImplementation(() => ({ start: new Date() })); (AlertingEventLogger as jest.Mock).mockImplementation(() => alertingEventLogger); + logger.get.mockImplementation(() => logger); }); test('updates rule saved object execution status and writes to event log entry when task is cancelled mid-execution', async () => { @@ -186,7 +188,6 @@ describe('Task Runner Cancel', () => { await taskRunner.cancel(); await promise; - const logger = taskRunnerFactoryInitializerParams.logger; expect(logger.debug).toHaveBeenNthCalledWith( 3, `Aborting any in-progress ES searches for rule type test with id 1` @@ -390,7 +391,6 @@ describe('Task Runner Cancel', () => { }); function testLogger() { - const logger = taskRunnerFactoryInitializerParams.logger; expect(logger.debug).toHaveBeenCalledTimes(7); expect(logger.debug).nthCalledWith(1, 'executing rule test:1 at 1970-01-01T00:00:00.000Z'); expect(logger.debug).nthCalledWith( diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 632d0489a9bb7..f1917a079a26d 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -17,6 +17,7 @@ import { IScopedClusterClient, SavedObjectAttributes, SavedObjectsClientContract, + Logger, } from '@kbn/core/server'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { RuleTypeRegistry as OrigruleTypeRegistry } from './rule_type_registry'; @@ -103,6 +104,7 @@ export interface RuleExecutorOptions< tags: string[]; createdBy: string | null; updatedBy: string | null; + logger: Logger; } export interface RuleParamsAndRefs { diff --git a/x-pack/plugins/apm/public/components/app/trace_explorer/index.tsx b/x-pack/plugins/apm/public/components/app/trace_explorer/index.tsx index 2e664ac756d6d..47287084386ad 100644 --- a/x-pack/plugins/apm/public/components/app/trace_explorer/index.tsx +++ b/x-pack/plugins/apm/public/components/app/trace_explorer/index.tsx @@ -5,14 +5,14 @@ * 2.0. */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { TraceSearchQuery, TraceSearchType, } from '../../../../common/trace_explorer'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useFetcher, FETCH_STATUS } from '../../../hooks/use_fetcher'; +import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { ApmDatePicker } from '../../shared/date_picker/apm_date_picker'; import { fromQuery, toQuery, push } from '../../shared/links/url_helpers'; @@ -20,6 +20,10 @@ import { useWaterfallFetcher } from '../transaction_details/use_waterfall_fetche import { WaterfallWithSummary } from '../transaction_details/waterfall_with_summary'; import { TraceSearchBox } from './trace_search_box'; +const INITIAL_DATA = { + traceSamples: [], +}; + export function TraceExplorer() { const [query, setQuery] = useState({ query: '', @@ -54,7 +58,11 @@ export function TraceExplorer() { rangeTo, }); - const { data: traceSamplesData, status: traceSamplesStatus } = useFetcher( + const { + data = INITIAL_DATA, + status, + error, + } = useFetcher( (callApmApi) => { return callApmApi('GET /internal/apm/traces/find', { params: { @@ -72,7 +80,7 @@ export function TraceExplorer() { ); useEffect(() => { - const nextSample = traceSamplesData?.samples[0]; + const nextSample = data.traceSamples[0]; const nextWaterfallItemId = ''; history.replace({ ...history.location, @@ -83,18 +91,23 @@ export function TraceExplorer() { waterfallItemId: nextWaterfallItemId, }), }); - }, [traceSamplesData, history]); + }, [data, history]); - const { waterfall, status: waterfallStatus } = useWaterfallFetcher({ + const waterfallFetchResult = useWaterfallFetcher({ traceId, transactionId, start, end, }); - const isLoading = - traceSamplesStatus === FETCH_STATUS.LOADING || - waterfallStatus === FETCH_STATUS.LOADING; + const traceSamplesFetchResult = useMemo( + () => ({ + data, + status, + error, + }), + [data, status, error] + ); return ( @@ -127,8 +140,9 @@ export function TraceExplorer() { { push(history, { query: { @@ -145,11 +159,12 @@ export function TraceExplorer() { }, }); }} - traceSamples={traceSamplesData?.samples ?? []} - waterfall={waterfall} detailTab={detailTab} waterfallItemId={waterfallItemId} - serviceName={waterfall.entryWaterfallTransaction?.doc.service.name} + serviceName={ + waterfallFetchResult.waterfall.entryWaterfallTransaction?.doc + .service.name + } /> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx index 1624bda055390..29232fd144972 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx @@ -87,8 +87,11 @@ describe('transaction_details/distribution', () => { , { wrapper: Wrapper } @@ -112,8 +115,11 @@ describe('transaction_details/distribution', () => { ); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx index fcc70bed96e28..73b224d60aaa4 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx @@ -12,9 +12,7 @@ import { useHistory } from 'react-router-dom'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; -import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; -import type { TabContentProps } from '../types'; import { useWaterfallFetcher } from '../use_waterfall_fetcher'; import { WaterfallWithSummary } from '../waterfall_with_summary'; @@ -26,21 +24,20 @@ import { HeightRetainer } from '../../../shared/height_retainer'; import { fromQuery, toQuery } from '../../../shared/links/url_helpers'; import { TransactionTab } from '../waterfall_with_summary/transaction_tabs'; import { useTransactionDistributionChartData } from './use_transaction_distribution_chart_data'; +import { TraceSamplesFetchResult } from '../../../../hooks/use_transaction_trace_samples_fetcher'; interface TransactionDistributionProps { onChartSelection: (event: XYBrushEvent) => void; onClearSelection: () => void; selection?: [number, number]; - traceSamples: TabContentProps['traceSamples']; - traceSamplesStatus: FETCH_STATUS; + traceSamplesFetchResult: TraceSamplesFetchResult; } export function TransactionDistribution({ onChartSelection, onClearSelection, selection, - traceSamples, - traceSamplesStatus, + traceSamplesFetchResult, }: TransactionDistributionProps) { const { urlParams } = useLegacyUrlParams(); const { traceId, transactionId } = urlParams; @@ -52,7 +49,7 @@ export function TransactionDistribution({ const { start, end } = useTimeRange({ rangeFrom, rangeTo }); const history = useHistory(); - const { waterfall, status: waterfallStatus } = useWaterfallFetcher({ + const waterfallFetchResult = useWaterfallFetcher({ traceId, transactionId, start, @@ -65,12 +62,10 @@ export function TransactionDistribution({ } = useApmParams('/services/{serviceName}/transactions/view'); const { serviceName } = useApmServiceContext(); - const isLoading = - waterfallStatus === FETCH_STATUS.LOADING || - traceSamplesStatus === FETCH_STATUS.LOADING; const markerCurrentEvent = - waterfall.entryWaterfallTransaction?.doc.transaction.duration.us; + waterfallFetchResult.waterfall.entryWaterfallTransaction?.doc.transaction + .duration.us; const { chartData, @@ -121,9 +116,8 @@ export function TransactionDistribution({ serviceName={serviceName} waterfallItemId={waterfallItemId} detailTab={detailTab as TransactionTab | undefined} - waterfall={waterfall} - isLoading={isLoading} - traceSamples={traceSamples} + waterfallFetchResult={waterfallFetchResult} + traceSamplesFetchResult={traceSamplesFetchResult} />
      diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/failed_transactions_correlations_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/failed_transactions_correlations_tab.tsx index 3044d365e1958..a0a69629d0d2c 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/failed_transactions_correlations_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/failed_transactions_correlations_tab.tsx @@ -18,8 +18,7 @@ import { useLicenseContext } from '../../../context/license/use_license_context' import { LicensePrompt } from '../../shared/license_prompt'; import { FailedTransactionsCorrelations } from '../correlations/failed_transactions_correlations'; - -import type { TabContentProps } from './types'; +import { TabContentProps } from './transaction_details_tabs'; function FailedTransactionsCorrelationsTab({ onFilter }: TabContentProps) { const license = useLicenseContext(); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/latency_correlations_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/latency_correlations_tab.tsx index e3dec8b3d9aa3..1fef9ac0dda66 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/latency_correlations_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/latency_correlations_tab.tsx @@ -18,8 +18,7 @@ import { useLicenseContext } from '../../../context/license/use_license_context' import { LicensePrompt } from '../../shared/license_prompt'; import { LatencyCorrelations } from '../correlations/latency_correlations'; - -import type { TabContentProps } from './types'; +import { TabContentProps } from './transaction_details_tabs'; function LatencyCorrelationsTab({ onFilter }: TabContentProps) { const license = useLicenseContext(); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx index d83211a72ea59..79919c5cdd332 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx @@ -10,15 +10,14 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { TransactionDistribution } from './distribution'; -import type { TabContentProps } from './types'; +import { TabContentProps } from './transaction_details_tabs'; function TraceSamplesTab({ selectSampleFromChartSelection, clearChartSelection, sampleRangeFrom, sampleRangeTo, - traceSamples, - traceSamplesStatus, + traceSamplesFetchResult, }: TabContentProps) { return ( ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index 742cd6f9e7a97..c99703d4f90f8 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -11,9 +11,13 @@ import { omit } from 'lodash'; import { useHistory } from 'react-router-dom'; import { EuiPanel, EuiSpacer, EuiTabs, EuiTab } from '@elastic/eui'; +import { XYBrushEvent } from '@elastic/charts'; import { useLegacyUrlParams } from '../../../context/url_params_context/use_url_params'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useTransactionTraceSamplesFetcher } from '../../../hooks/use_transaction_trace_samples_fetcher'; +import { + TraceSamplesFetchResult, + useTransactionTraceSamplesFetcher, +} from '../../../hooks/use_transaction_trace_samples_fetcher'; import { maybe } from '../../../../common/utils/maybe'; import { fromQuery, toQuery } from '../../shared/links/url_helpers'; @@ -24,6 +28,15 @@ import { traceSamplesTab } from './trace_samples_tab'; import { useSampleChartSelection } from '../../../hooks/use_sample_chart_selection'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; +export interface TabContentProps { + clearChartSelection: () => void; + onFilter: () => void; + sampleRangeFrom?: number; + sampleRangeTo?: number; + selectSampleFromChartSelection: (selection: XYBrushEvent) => void; + traceSamplesFetchResult: TraceSamplesFetchResult; +} + const tabs = [ traceSamplesTab, latencyCorrelationsTab, @@ -41,15 +54,14 @@ export function TransactionDetailsTabs() { tabs.find((tab) => tab.key === currentTab) ?? traceSamplesTab; const { environment, kuery, transactionName } = query; - const { traceSamplesData, traceSamplesStatus } = - useTransactionTraceSamplesFetcher({ - transactionName, - kuery, - environment, - }); + + const traceSamplesFetchResult = useTransactionTraceSamplesFetcher({ + transactionName, + kuery, + environment, + }); const { sampleRangeFrom, sampleRangeTo, transactionId, traceId } = urlParams; - const { traceSamples } = traceSamplesData; const { clearChartSelection, selectSampleFromChartSelection } = useSampleChartSelection(); @@ -65,14 +77,19 @@ export function TransactionDetailsTabs() { }, [traceSamplesTabKey]); useEffect(() => { - const selectedSample = traceSamples.find( + const selectedSample = traceSamplesFetchResult.data?.traceSamples.find( (sample) => sample.transactionId === transactionId && sample.traceId === traceId ); - if (traceSamplesStatus === FETCH_STATUS.SUCCESS && !selectedSample) { + if ( + traceSamplesFetchResult.status === FETCH_STATUS.SUCCESS && + !selectedSample + ) { // selected sample was not found. select a new one: - const preferredSample = maybe(traceSamples[0]); + const preferredSample = maybe( + traceSamplesFetchResult.data?.traceSamples[0] + ); history.replace({ ...history.location, @@ -85,7 +102,7 @@ export function TransactionDetailsTabs() { }), }); } - }, [history, traceSamples, transactionId, traceId, traceSamplesStatus]); + }, [history, transactionId, traceId, traceSamplesFetchResult]); return ( <> @@ -112,8 +129,7 @@ export function TransactionDetailsTabs() { sampleRangeFrom, sampleRangeTo, selectSampleFromChartSelection, - traceSamples, - traceSamplesStatus, + traceSamplesFetchResult, }} /> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/types.ts b/x-pack/plugins/apm/public/components/app/transaction_details/types.ts deleted file mode 100644 index 2014f7588293d..0000000000000 --- a/x-pack/plugins/apm/public/components/app/transaction_details/types.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { XYBrushEvent } from '@elastic/charts'; - -import type { TraceSample } from '../../../hooks/use_transaction_trace_samples_fetcher'; -import { FETCH_STATUS } from '../../../hooks/use_fetcher'; - -export interface TabContentProps { - clearChartSelection: () => void; - onFilter: () => void; - sampleRangeFrom?: number; - sampleRangeTo?: number; - selectSampleFromChartSelection: (selection: XYBrushEvent) => void; - traceSamples: TraceSample[]; - traceSamplesStatus: FETCH_STATUS; -} diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/use_waterfall_fetcher.ts b/x-pack/plugins/apm/public/components/app/transaction_details/use_waterfall_fetcher.ts index 793524c7e17f1..890f5c98cb6fc 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/use_waterfall_fetcher.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/use_waterfall_fetcher.ts @@ -16,6 +16,7 @@ const INITIAL_DATA: APIReturnType<'GET /internal/apm/traces/{traceId}'> = { exceedsMax: false, linkedChildrenOfSpanCountBySpanId: {}, }; +export type WaterfallFetchResult = ReturnType; export function useWaterfallFetcher({ traceId, diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx index 61b814a598e87..57d630393f9a9 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx @@ -12,22 +12,22 @@ import { EuiPagination, EuiSpacer, EuiTitle, + EuiLoadingContent, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; -import { LoadingStatePrompt } from '../../../shared/loading_state_prompt'; import { TransactionSummary } from '../../../shared/summary/transaction_summary'; import { TransactionActionMenu } from '../../../shared/transaction_action_menu/transaction_action_menu'; -import type { TraceSample } from '../../../../hooks/use_transaction_trace_samples_fetcher'; import { MaybeViewTraceLink } from './maybe_view_trace_link'; import { TransactionTab, TransactionTabs } from './transaction_tabs'; -import { IWaterfall } from './waterfall_container/waterfall/waterfall_helpers/waterfall_helpers'; import { Environment } from '../../../../../common/environment_rt'; +import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; +import { TraceSamplesFetchResult } from '../../../../hooks/use_transaction_trace_samples_fetcher'; +import { WaterfallFetchResult } from '../use_waterfall_fetcher'; interface Props { - waterfall: IWaterfall; - isLoading: boolean; - traceSamples: TraceSample[]; + waterfallFetchResult: WaterfallFetchResult; + traceSamplesFetchResult: TraceSamplesFetchResult; environment: Environment; onSampleClick: (sample: { transactionId: string; traceId: string }) => void; onTabClick: (tab: string) => void; @@ -37,9 +37,8 @@ interface Props { } export function WaterfallWithSummary({ - waterfall, - isLoading, - traceSamples, + waterfallFetchResult, + traceSamplesFetchResult, environment, onSampleClick, onTabClick, @@ -51,17 +50,27 @@ export function WaterfallWithSummary({ useEffect(() => { setSampleActivePage(0); - }, [traceSamples]); + }, [traceSamplesFetchResult.data.traceSamples]); const goToSample = (index: number) => { setSampleActivePage(index); - const sample = traceSamples[index]; + const sample = traceSamplesFetchResult.data.traceSamples[index]; onSampleClick(sample); }; - const { entryWaterfallTransaction } = waterfall; + const { entryWaterfallTransaction } = waterfallFetchResult.waterfall; + const isLoading = + waterfallFetchResult.status === FETCH_STATUS.LOADING || + traceSamplesFetchResult.status === FETCH_STATUS.LOADING; + const isSucceded = + waterfallFetchResult.status === FETCH_STATUS.SUCCESS && + traceSamplesFetchResult.status === FETCH_STATUS.SUCCESS; - if ((!entryWaterfallTransaction || traceSamples.length === 0) && !isLoading) { + if ( + !entryWaterfallTransaction && + traceSamplesFetchResult.data.traceSamples.length === 0 && + isSucceded + ) { return ( - {traceSamples.length > 0 && ( + {traceSamplesFetchResult.data.traceSamples.length > 0 && ( @@ -123,25 +132,34 @@ export function WaterfallWithSummary({ {isLoading || !entryTransaction ? ( - - ) : ( <> - - + + ) : ( + )} + + + + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/transaction_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/transaction_tabs.tsx index f4192f501aa2c..e3fdaeea24846 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/transaction_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/transaction_tabs.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; +import { EuiSpacer, EuiTab, EuiTabs, EuiLoadingContent } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { LogStream } from '@kbn/infra-plugin/public'; import React from 'react'; @@ -15,7 +15,8 @@ import { WaterfallContainer } from './waterfall_container'; import { IWaterfall } from './waterfall_container/waterfall/waterfall_helpers/waterfall_helpers'; interface Props { - transaction: Transaction; + transaction?: Transaction; + isLoading: boolean; waterfall: IWaterfall; detailTab?: TransactionTab; serviceName?: string; @@ -26,6 +27,7 @@ interface Props { export function TransactionTabs({ transaction, waterfall, + isLoading, detailTab, waterfallItemId, serviceName, @@ -36,7 +38,7 @@ export function TransactionTabs({ const TabContent = currentTab.component; return ( - + <> {tabs.map(({ key, label }) => { return ( @@ -54,14 +56,17 @@ export function TransactionTabs({ - - - + {isLoading || !transaction ? ( + + ) : ( + + )} + ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_legends.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_legends.tsx index 30d4b0049d1bd..5aeae556f33ec 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_legends.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall_legends.tsx @@ -37,7 +37,7 @@ const LEGEND_LABELS = { }; export function WaterfallLegends({ legends, type }: Props) { return ( - + {LEGEND_LABELS[type]} diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx index b47695ebed74c..76bc9ffb9f440 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/index.tsx @@ -84,7 +84,7 @@ export function LatencyChart({ height, kuery }: Props) { - +

      diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts index f0906eef3ab09..9bb2b68266827 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_trace_samples_fetcher.ts @@ -5,21 +5,21 @@ * 2.0. */ +import { useMemo } from 'react'; import { useFetcher } from './use_fetcher'; import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; import { useApmServiceContext } from '../context/apm_service/use_apm_service_context'; import { useApmParams } from './use_apm_params'; import { useTimeRange } from './use_time_range'; -export interface TraceSample { - traceId: string; - transactionId: string; -} - const INITIAL_DATA = { - traceSamples: [] as TraceSample[], + traceSamples: [], }; +export type TraceSamplesFetchResult = ReturnType< + typeof useTransactionTraceSamplesFetcher +>; + export function useTransactionTraceSamplesFetcher({ transactionName, kuery, @@ -87,9 +87,12 @@ export function useTransactionTraceSamplesFetcher({ ] ); - return { - traceSamplesData: data, - traceSamplesStatus: status, - traceSamplesError: error, - }; + return useMemo( + () => ({ + data, + status, + error, + }), + [data, status, error] + ); } diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_instructions.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_instructions.tsx index 5c5bb3282d217..c7244002e59f5 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_instructions.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_instructions.tsx @@ -8,7 +8,11 @@ import React from 'react'; import { EuiCodeBlock, EuiSpacer } from '@elastic/eui'; import { OpenTelemetryInstructions } from './opentelemetry_instructions'; -import { getApmAgentCommands } from './commands/get_apm_agent_commands'; +import { + getApmAgentCommands, + getApmAgentVariables, +} from './commands/get_apm_agent_commands'; +import { AgentConfigurationTable } from './agent_config_table'; export function AgentConfigInstructions({ variantId, @@ -19,6 +23,11 @@ export function AgentConfigInstructions({ apmServerUrl?: string; secretToken?: string; }) { + const defaultValues = { + apmServiceName: 'my-service-name', + apmEnvironment: 'production', + }; + if (variantId === 'openTelemetry') { return ( <> @@ -37,11 +46,20 @@ export function AgentConfigInstructions({ apmServerUrl, secretToken, }, + defaultValues, }); + const variables = getApmAgentVariables(variantId); + return ( <> + + + {commands} diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_table.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_table.tsx new file mode 100644 index 0000000000000..b06ad4be25dae --- /dev/null +++ b/x-pack/plugins/apm/public/tutorial/config_agent/agent_config_table.tsx @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { ValuesType } from 'utility-types'; +import { get } from 'lodash'; +import { EuiBasicTable, EuiText, EuiBasicTableColumn } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export function AgentConfigurationTable({ + variables, + data, +}: { + variables: { [key: string]: string }; + data: { + apmServerUrl?: string; + secretToken?: string; + apmServiceName: string; + apmEnvironment: string; + }; +}) { + if (!variables) return null; + + const columns: Array>> = [ + { + field: 'setting', + name: i18n.translate('xpack.apm.tutorial.agent.column.configSettings', { + defaultMessage: 'Configuration setting', + }), + }, + { + field: 'value', + name: i18n.translate('xpack.apm.tutorial.agent.column.configValue', { + defaultMessage: 'Configuration value', + }), + render: (_, { value }) => ( + + {value} + + ), + }, + ]; + + const items = Object.keys(variables).map((k) => ({ + setting: variables[k], + value: get(data, k), // TODO do we want default values? + })); + return ; +} diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts index 047b8808f13ce..4379f15c59cde 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/django.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const djangoVariables = { + apmServiceName: 'SERVICE_NAME', + apmServerUrl: 'SERVER_URL', + secretToken: 'SECRET_TOKEN', + apmEnvironment: 'ENVIRONMENT', +}; + export const django = `# ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.addAgentComment', { @@ -31,7 +38,7 @@ ELASTIC_APM = { defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', } )} -#'SERVICE_NAME': 'unknown-python-service', +#'${djangoVariables.apmServiceName}': '{{{apmServiceName}}}', # ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment', @@ -39,7 +46,7 @@ ELASTIC_APM = { defaultMessage: 'Use if APM Server requires a secret token', } )} -'SECRET_TOKEN': '{{{secretToken}}}', +'${djangoVariables.secretToken}': '{{{secretToken}}}', # ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment', @@ -49,7 +56,7 @@ ELASTIC_APM = { values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -'SERVER_URL': '{{{apmServerUrl}}}', +'${djangoVariables.apmServerUrl}': '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment', @@ -57,7 +64,7 @@ ELASTIC_APM = { defaultMessage: 'Set the service environment', } )} -'ENVIRONMENT': 'production', +'${djangoVariables.apmEnvironment}': '{{{apmEnvironment}}}', } # ${i18n.translate( diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts index e083a2b45c716..e52b908748103 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/dotnet.ts @@ -4,11 +4,18 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + +export const dotnetVariables = { + apmServiceName: 'ServiceName', + secretToken: 'SecretToken', + apmServerUrl: 'ServerUrl', + apmEnvironment: 'Environment', +}; export const dotnet = `{ -"ElasticApm": { -"SecretToken": "{{{secretToken}}}", -"ServerUrls": "{{{apmServerUrl}}}", //Set custom APM Server URL (default: http://localhost:8200) -"ServiceName": "MyApp", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application -"Environment": "production", // Set the service environment -} + "ElasticApm": { + "${dotnetVariables.apmServiceName}": "{{{apmServiceName}}}", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + "${dotnetVariables.secretToken}": "{{{secretToken}}}", + "${dotnetVariables.apmServerUrl}": "{{{apmServerUrl}}}", //Set custom APM Server URL (default: http://localhost:8200) + "${dotnetVariables.apmEnvironment}": "{{{apmEnvironment}}}", // Set the service environment + } }`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts index 51e69b08a24a5..11423c4e059db 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/flask.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const flaskVariables = { + apmServiceName: 'SERVICE_NAME', + secretToken: 'SECRET_TOKEN', + apmServerUrl: 'SERVER_URL', + apmEnvironment: 'ENVIRONMENT', +}; + export const flask = `# ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment', { @@ -38,7 +45,7 @@ app.config['ELASTIC_APM'] = { defaultMessage: 'a-z, A-Z, 0-9, -, _, and space', } )} -#'SERVICE_NAME': 'unknown-python-service', +#'${flaskVariables.apmServiceName}': '{{{apmServiceName}}}', # ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment', @@ -46,7 +53,7 @@ app.config['ELASTIC_APM'] = { defaultMessage: 'Use if APM Server requires a secret token', } )} -'SECRET_TOKEN': '{{{secretToken}}}', +'${flaskVariables.secretToken}': '{{{secretToken}}}', # ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment', @@ -56,7 +63,7 @@ app.config['ELASTIC_APM'] = { values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -'SERVER_URL': '{{{apmServerUrl}}}', +'${flaskVariables.apmServerUrl}': '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment', @@ -64,7 +71,7 @@ app.config['ELASTIC_APM'] = { defaultMessage: 'Set the service environment', } )} -'ENVIRONMENT': 'production', +'${flaskVariables.apmEnvironment}': '{{{apmEnvironment}}}', } apm = ElasticAPM(app)`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.test.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.test.ts index ba21a35768c42..efbcfae955a55 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.test.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.test.ts @@ -8,6 +8,10 @@ import { getApmAgentCommands } from './get_apm_agent_commands'; describe('getCommands', () => { + const defaultValues = { + apmServiceName: 'my-service-name', + apmEnvironment: 'production', + }; describe('unknown agent', () => { it('renders empty command', () => { const commands = getApmAgentCommands({ @@ -16,6 +20,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).toBe(''); }); @@ -25,15 +30,16 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'java', policyDetails: {}, + defaultValues, }); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls= \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url= \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); it('renders with secret token and url', () => { @@ -43,16 +49,17 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=localhost:8220 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token=foobar \\\\ + -Delastic.apm.server_url=localhost:8220 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); }); @@ -61,6 +68,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'js', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -68,7 +76,7 @@ describe('getCommands', () => { var apm = initApm({ // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space) - serviceName: 'your-app-name', + serviceName: 'my-service-name', // Set custom APM Server URL (default: http://localhost:8200) serverUrl: '', @@ -88,6 +96,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -95,7 +104,7 @@ describe('getCommands', () => { var apm = initApm({ // Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space) - serviceName: 'your-app-name', + serviceName: 'my-service-name', // Set custom APM Server URL (default: http://localhost:8200) serverUrl: 'localhost:8220', @@ -114,6 +123,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'node', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -122,7 +132,7 @@ describe('getCommands', () => { // Override the service name from package.json // Allowed characters: a-z, A-Z, 0-9, -, _, and space - serviceName: '', + serviceName: 'my-service-name', // Use if APM Server requires a secret token secretToken: '', @@ -142,6 +152,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -150,7 +161,7 @@ describe('getCommands', () => { // Override the service name from package.json // Allowed characters: a-z, A-Z, 0-9, -, _, and space - serviceName: '', + serviceName: 'my-service-name', // Use if APM Server requires a secret token secretToken: 'foobar', @@ -169,6 +180,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'django', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -181,7 +193,7 @@ describe('getCommands', () => { ELASTIC_APM = { # Set the required service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space - #'SERVICE_NAME': 'unknown-python-service', + #'SERVICE_NAME': 'my-service-name', # Use if APM Server requires a secret token 'SECRET_TOKEN': '', @@ -207,6 +219,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -219,7 +232,7 @@ describe('getCommands', () => { ELASTIC_APM = { # Set the required service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space - #'SERVICE_NAME': 'unknown-python-service', + #'SERVICE_NAME': 'my-service-name', # Use if APM Server requires a secret token 'SECRET_TOKEN': 'foobar', @@ -244,6 +257,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'flask', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -257,7 +271,7 @@ describe('getCommands', () => { app.config['ELASTIC_APM'] = { # Set the required service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space - #'SERVICE_NAME': 'unknown-python-service', + #'SERVICE_NAME': 'my-service-name', # Use if APM Server requires a secret token 'SECRET_TOKEN': '', @@ -279,6 +293,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -292,7 +307,7 @@ describe('getCommands', () => { app.config['ELASTIC_APM'] = { # Set the required service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space - #'SERVICE_NAME': 'unknown-python-service', + #'SERVICE_NAME': 'my-service-name', # Use if APM Server requires a secret token 'SECRET_TOKEN': 'foobar', @@ -313,6 +328,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'rails', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -320,7 +336,7 @@ describe('getCommands', () => { # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space # Defaults to the name of your Rails app - service_name: 'my-service' + service_name: 'my-service-name' # Use if APM Server requires a secret token secret_token: '' @@ -339,6 +355,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -346,7 +363,7 @@ describe('getCommands', () => { # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space # Defaults to the name of your Rails app - service_name: 'my-service' + service_name: 'my-service-name' # Use if APM Server requires a secret token secret_token: 'foobar' @@ -364,6 +381,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'rack', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -371,7 +389,7 @@ describe('getCommands', () => { # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space # Defaults to the name of your Rack app's class. - service_name: 'my-service' + service_name: 'my-service-name' # Use if APM Server requires a token secret_token: '' @@ -390,6 +408,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -397,7 +416,7 @@ describe('getCommands', () => { # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space # Defaults to the name of your Rack app's class. - service_name: 'my-service' + service_name: 'my-service-name' # Use if APM Server requires a token secret_token: 'foobar' @@ -415,6 +434,7 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'go', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -422,16 +442,16 @@ describe('getCommands', () => { # Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space. # If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used. - export ELASTIC_APM_SERVICE_NAME= - - # Set custom APM Server URL (default: http://localhost:8200) - export ELASTIC_APM_SERVER_URL= + export ELASTIC_APM_SERVICE_NAME=my-service-name # Use if APM Server requires a secret token export ELASTIC_APM_SECRET_TOKEN= + # Set custom APM Server URL (default: http://localhost:8200) + export ELASTIC_APM_SERVER_URL= + # Set the service environment - export ELASTIC_APM_ENVIRONMENT= + export ELASTIC_APM_ENVIRONMENT=production " `); }); @@ -442,6 +462,7 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` @@ -449,16 +470,16 @@ describe('getCommands', () => { # Set the service name. Allowed characters: # a-z, A-Z, 0-9, -, _, and space. # If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used. - export ELASTIC_APM_SERVICE_NAME= - - # Set custom APM Server URL (default: http://localhost:8200) - export ELASTIC_APM_SERVER_URL=localhost:8220 + export ELASTIC_APM_SERVICE_NAME=my-service-name # Use if APM Server requires a secret token export ELASTIC_APM_SECRET_TOKEN=foobar + # Set custom APM Server URL (default: http://localhost:8200) + export ELASTIC_APM_SERVER_URL=localhost:8220 + # Set the service environment - export ELASTIC_APM_ENVIRONMENT= + export ELASTIC_APM_ENVIRONMENT=production " `); }); @@ -468,16 +489,17 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'dotnet', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` "{ - \\"ElasticApm\\": { - \\"SecretToken\\": \\"\\", - \\"ServerUrls\\": \\"\\", //Set custom APM Server URL (default: http://localhost:8200) - \\"ServiceName\\": \\"MyApp\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application - \\"Environment\\": \\"production\\", // Set the service environment - } + \\"ElasticApm\\": { + \\"ServiceName\\": \\"my-service-name\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + \\"SecretToken\\": \\"\\", + \\"ServerUrl\\": \\"\\", //Set custom APM Server URL (default: http://localhost:8200) + \\"Environment\\": \\"production\\", // Set the service environment + } }" `); }); @@ -488,16 +510,17 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` "{ - \\"ElasticApm\\": { - \\"SecretToken\\": \\"foobar\\", - \\"ServerUrls\\": \\"localhost:8220\\", //Set custom APM Server URL (default: http://localhost:8200) - \\"ServiceName\\": \\"MyApp\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application - \\"Environment\\": \\"production\\", // Set the service environment - } + \\"ElasticApm\\": { + \\"ServiceName\\": \\"my-service-name\\", //allowed characters: a-z, A-Z, 0-9, -, _, and space. Default is the entry assembly of the application + \\"SecretToken\\": \\"foobar\\", + \\"ServerUrl\\": \\"localhost:8220\\", //Set custom APM Server URL (default: http://localhost:8200) + \\"Environment\\": \\"production\\", // Set the service environment + } }" `); }); @@ -507,12 +530,14 @@ describe('getCommands', () => { const commands = getApmAgentCommands({ variantId: 'php', policyDetails: {}, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` - "elastic_apm.server_url=\\"\\" + "elastic_apm.service_name=\\"my-service-name\\" elastic_apm.secret_token=\\"\\" - elastic_apm.service_name=\\"My service\\" + elastic_apm.server_url=\\"\\" + elastic_apm.environment=\\"production\\" " `); }); @@ -523,12 +548,14 @@ describe('getCommands', () => { apmServerUrl: 'localhost:8220', secretToken: 'foobar', }, + defaultValues, }); expect(commands).not.toBe(''); expect(commands).toMatchInlineSnapshot(` - "elastic_apm.server_url=\\"localhost:8220\\" + "elastic_apm.service_name=\\"my-service-name\\" elastic_apm.secret_token=\\"foobar\\" - elastic_apm.service_name=\\"My service\\" + elastic_apm.server_url=\\"localhost:8220\\" + elastic_apm.environment=\\"production\\" " `); }); diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.ts index d217397f03f2e..ab184a8d94cd0 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/get_apm_agent_commands.ts @@ -5,16 +5,16 @@ * 2.0. */ import Mustache from 'mustache'; -import { java } from './java'; -import { node } from './node'; -import { django } from './django'; -import { flask } from './flask'; -import { rails } from './rails'; -import { rack } from './rack'; -import { go } from './go'; -import { dotnet } from './dotnet'; -import { php } from './php'; -import { rum, rumScript } from './rum'; +import { java, javaVariables } from './java'; +import { node, nodeVariables } from './node'; +import { django, djangoVariables } from './django'; +import { flask, flaskVariables } from './flask'; +import { rails, railsVariables } from './rails'; +import { rack, rackVariables } from './rack'; +import { go, goVariables } from './go'; +import { dotnet, dotnetVariables } from './dotnet'; +import { php, phpVariables } from './php'; +import { rum, rumScript, rumVariables } from './rum'; const apmAgentCommandsMap: Record = { java, @@ -30,19 +30,46 @@ const apmAgentCommandsMap: Record = { js_script: rumScript, }; +interface Variables { + [key: string]: string; +} + +const apmAgentVariablesMap: Record = { + java: javaVariables, + node: nodeVariables, + django: djangoVariables, + flask: flaskVariables, + rails: railsVariables, + rack: rackVariables, + go: goVariables, + dotnet: dotnetVariables, + php: phpVariables, + js: rumVariables, +}; + export function getApmAgentCommands({ variantId, policyDetails, + defaultValues, }: { variantId: string; policyDetails: { apmServerUrl?: string; secretToken?: string; }; + defaultValues: { + apmServiceName: string; + apmEnvironment: string; + }; }) { const commands = apmAgentCommandsMap[variantId]; if (!commands) { return ''; } - return Mustache.render(commands, policyDetails); + + return Mustache.render(commands, { ...policyDetails, ...defaultValues }); +} + +export function getApmAgentVariables(variantId: string) { + return apmAgentVariablesMap[variantId]; } diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts index a3900420d6fde..27bb7b6c46aae 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/go.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const goVariables = { + apmServiceName: 'ELASTIC_APM_SERVICE_NAME', + secretToken: 'ELASTIC_APM_SECRET_TOKEN', + apmServerUrl: 'ELASTIC_APM_SERVER_URL', + apmEnvironment: 'ELASTIC_APM_ENVIRONMENT', +}; + export const go = `# ${i18n.translate( 'xpack.apm.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment', { @@ -28,25 +35,25 @@ export const go = `# ${i18n.translate( 'If ELASTIC_APM_SERVICE_NAME is not specified, the executable name will be used.', } )} -export ELASTIC_APM_SERVICE_NAME= +export ${goVariables.apmServiceName}={{{apmServiceName}}} # ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment', + 'xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', { - defaultMessage: - 'Set custom APM Server URL (default: {defaultApmServerUrl})', - values: { defaultApmServerUrl: 'http://localhost:8200' }, + defaultMessage: 'Use if APM Server requires a secret token', } )} -export ELASTIC_APM_SERVER_URL={{{apmServerUrl}}} +export ${goVariables.secretToken}={{{secretToken}}} # ${i18n.translate( - 'xpack.apm.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment', + 'xpack.apm.tutorial.goClient.configure.commands.setCustomApmServerUrlComment', { - defaultMessage: 'Use if APM Server requires a secret token', + defaultMessage: + 'Set custom APM Server URL (default: {defaultApmServerUrl})', + values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -export ELASTIC_APM_SECRET_TOKEN={{{secretToken}}} +export ${goVariables.apmServerUrl}={{{apmServerUrl}}} # ${i18n.translate( 'xpack.apm.tutorial.goClient.configure.commands.setServiceEnvironment', @@ -54,5 +61,5 @@ export ELASTIC_APM_SECRET_TOKEN={{{secretToken}}} defaultMessage: 'Set the service environment', } )} -export ELASTIC_APM_ENVIRONMENT= +export ${goVariables.apmEnvironment}={{{apmEnvironment}}} `; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts index 249907a9b0c4b..2d056b3a242f3 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/java.ts @@ -5,10 +5,17 @@ * 2.0. */ +export const javaVariables = { + apmServiceName: 'Delastic.apm.service_name', + secretToken: 'Delastic.apm.secret_token', + apmServerUrl: 'Delastic.apm.server_url', + apmEnvironment: 'Delastic.apm.environment', +}; + export const java = `java -javaagent:/path/to/elastic-apm-agent-.jar \\ --Delastic.apm.service_name=my-application \\ --Delastic.apm.server_urls={{{apmServerUrl}}} \\ --Delastic.apm.secret_token={{{secretToken}}} \\ --Delastic.apm.environment=production \\ +-${javaVariables.apmServiceName}={{{apmServiceName}}} \\ +-${javaVariables.secretToken}={{{secretToken}}} \\ +-${javaVariables.apmServerUrl}={{{apmServerUrl}}} \\ +-${javaVariables.apmEnvironment}=production \\ -Delastic.apm.application_packages=org.example \\ --jar my-application.jar`; +-jar {{{apmServiceName}}}.jar`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts index 31f9fac0ed480..8b8ba07a7cb9c 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/node.ts @@ -6,6 +6,13 @@ */ import { i18n } from '@kbn/i18n'; +export const nodeVariables = { + apmServiceName: 'serviceName', + secretToken: 'secretToken', + apmServerUrl: 'serverUrl', + apmEnvironment: 'environment', +}; + export const node = `// ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.addThisToTheFileTopComment', { @@ -27,7 +34,7 @@ var apm = require('elastic-apm-node').start({ defaultMessage: 'Allowed characters: a-z, A-Z, 0-9, -, _, and space', } )} -serviceName: '', +${nodeVariables.apmServiceName}: '{{{apmServiceName}}}', // ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.useIfApmRequiresTokenComment', @@ -35,7 +42,7 @@ serviceName: '', defaultMessage: 'Use if APM Server requires a secret token', } )} -secretToken: '{{{secretToken}}}', +${nodeVariables.secretToken}: '{{{secretToken}}}', // ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomApmServerUrlComment', @@ -45,7 +52,7 @@ secretToken: '{{{secretToken}}}', values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} -serverUrl: '{{{apmServerUrl}}}', +${nodeVariables.apmServerUrl}: '{{{apmServerUrl}}}', // ${i18n.translate( 'xpack.apm.tutorial.nodeClient.configure.commands.setCustomServiceEnvironmentComment', @@ -53,5 +60,5 @@ serverUrl: '{{{apmServerUrl}}}', defaultMessage: 'Set the service environment', } )} -environment: 'production' +${nodeVariables.apmEnvironment}: '{{{apmEnvironment}}}' })`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts index dba4147b8afbc..4ce1590bab6a2 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/php.ts @@ -4,8 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export const php = `elastic_apm.server_url="{{{apmServerUrl}}}" -elastic_apm.secret_token="{{{secretToken}}}" -elastic_apm.service_name="My service" +export const phpVariables = { + apmServiceName: 'elastic_apm.service_name', + secretToken: 'elastic_apm.secret_token', + apmServerUrl: 'elastic_apm.server_url', + apmEnvironment: 'elastic_apm.environment', +}; +export const php = `${phpVariables.apmServiceName}="{{{apmServiceName}}}" +${phpVariables.secretToken}="{{{secretToken}}}" +${phpVariables.apmServerUrl}="{{{apmServerUrl}}}" +${phpVariables.apmEnvironment}="{{{apmEnvironment}}}" `; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts index 9195ad9f15666..06fc6031bf32f 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rack.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const rackVariables = { + apmServiceName: 'service_name', + secretToken: 'secret_token', + apmServerUrl: 'server_url', + apmEnvironment: 'environment', +}; + export const rack = `# config/elastic_apm.yml: # ${i18n.translate( @@ -22,7 +29,7 @@ export const rack = `# config/elastic_apm.yml: defaultMessage: "Defaults to the name of your Rack app's class.", } )} -service_name: 'my-service' +${rackVariables.apmServiceName}: '{{{apmServiceName}}}' # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.useIfApmServerRequiresTokenComment', @@ -30,7 +37,7 @@ service_name: 'my-service' defaultMessage: 'Use if APM Server requires a token', } )} -secret_token: '{{{secretToken}}}' +${rackVariables.secretToken}: '{{{secretToken}}}' # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.setCustomApmServerComment', @@ -39,7 +46,7 @@ secret_token: '{{{secretToken}}}' values: { defaultServerUrl: 'http://localhost:8200' }, } )} -server_url: '{{{apmServerUrl}}}', +${rackVariables.apmServerUrl}: '{{{apmServerUrl}}}', # ${i18n.translate( 'xpack.apm.tutorial.rackClient.createConfig.commands.setServiceEnvironment', @@ -47,4 +54,4 @@ server_url: '{{{apmServerUrl}}}', defaultMessage: 'Set the service environment', } )} -environment: 'production'`; +${rackVariables.apmEnvironment}: '{{{apmEnvironment}}}'`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts index 0f8a5508e1ceb..c7d5971f43e3b 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rails.ts @@ -5,17 +5,24 @@ * 2.0. */ +export const railsVariables = { + apmServiceName: 'service_name', + secretToken: 'secret_token', + apmServerUrl: 'server_url', + apmEnvironment: 'environment', +}; + export const rails = `# config/elastic_apm.yml: # Set the service name - allowed characters: a-z, A-Z, 0-9, -, _ and space # Defaults to the name of your Rails app -service_name: 'my-service' +${railsVariables.apmServiceName}: '{{{apmServiceName}}}' # Use if APM Server requires a secret token -secret_token: '{{{secretToken}}}' +${railsVariables.secretToken}: '{{{secretToken}}}' # Set the custom APM Server URL (default: http://localhost:8200) -server_url: '{{{apmServerUrl}}}' +${railsVariables.apmServerUrl}: '{{{apmServerUrl}}}' # Set the service environment -environment: 'production'`; +${railsVariables.apmEnvironment}: '{{{apmEnvironment}}}'`; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts index f5de61f64c63a..32dca0dd4d784 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts +++ b/x-pack/plugins/apm/public/tutorial/config_agent/commands/rum.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; +export const rumVariables = { + apmServiceName: 'serviceName', + apmServerUrl: 'serverUrl', + apmServiceVersion: 'serviceVersion', + apmEnvironment: 'environment', +}; + export const rum = `import { init as initApm } from '@elastic/apm-rum' var apm = initApm({ @@ -17,7 +24,7 @@ var apm = initApm({ 'Set required service name (allowed characters: a-z, A-Z, 0-9, -, _, and space)', } )} - serviceName: 'your-app-name', + ${rumVariables.apmServiceName}: '{{{apmServiceName}}}', // ${i18n.translate( 'xpack.apm.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment', @@ -27,7 +34,7 @@ var apm = initApm({ values: { defaultApmServerUrl: 'http://localhost:8200' }, } )} - serverUrl: '{{{apmServerUrl}}}', + ${rumVariables.apmServerUrl}: '{{{apmServerUrl}}}', // ${i18n.translate( 'xpack.apm.tutorial.jsClient.installDependency.commands.setServiceVersionComment', @@ -44,15 +51,15 @@ var apm = initApm({ defaultMessage: 'Set the service environment', } )} - environment: 'production' + ${rumVariables.apmEnvironment}: '{{{apmEnvironment}}}' })`; export const rumScript = `\ `; diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx index c41f6df5369f6..b1ebe783518d0 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/index.test.tsx @@ -24,14 +24,14 @@ const fleetAgents = [ { id: '1', name: 'agent foo', - apmServerUrl: 'foo', - secretToken: 'foo', + apmServerUrl: 'foo url', + secretToken: 'foo token', }, { id: '2', name: 'agent bar', - apmServerUrl: 'bar', - secretToken: 'bar', + apmServerUrl: 'bar url', + secretToken: 'bar token', }, ]; @@ -87,12 +87,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url=http://localhost:8200 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); fireEvent.click(component.getByTestId('comboBoxToggleListButton')); @@ -101,12 +101,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=foo \\\\ - -Delastic.apm.secret_token=foo \\\\ + -Delastic.apm.service_name=my-service-name \\\\ + -Delastic.apm.secret_token=foo token \\\\ + -Delastic.apm.server_url=foo url \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); describe('running on prem', () => { @@ -138,12 +138,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url=http://localhost:8200 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); it('shows get started with fleet link when there are no fleet agents', async () => { @@ -174,12 +174,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url=http://localhost:8200 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); expectTextsInDocument(component, ['Get started with fleet']); }); @@ -216,12 +216,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=cloud_url \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token=cloud_token \\\\ + -Delastic.apm.server_url=cloud_url \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); it('selects policy elastic agent on cloud when available by default', async () => { @@ -255,12 +255,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=apm_cloud_url \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token=apm_cloud_token \\\\ + -Delastic.apm.server_url=apm_cloud_url \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); @@ -287,12 +287,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url=http://localhost:8200 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); }); @@ -350,12 +350,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=http://localhost:8200 \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token= \\\\ + -Delastic.apm.server_url=http://localhost:8200 \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); it('shows default standalone on cloud', async () => { @@ -387,12 +387,12 @@ describe('TutorialConfigAgent', () => { expect(commands).not.toEqual(''); expect(commands).toMatchInlineSnapshot(` "java -javaagent:/path/to/elastic-apm-agent-<version>.jar \\\\ - -Delastic.apm.service_name=my-application \\\\ - -Delastic.apm.server_urls=cloud_url \\\\ + -Delastic.apm.service_name=my-service-name \\\\ -Delastic.apm.secret_token=cloud_token \\\\ + -Delastic.apm.server_url=cloud_url \\\\ -Delastic.apm.environment=production \\\\ -Delastic.apm.application_packages=org.example \\\\ - -jar my-application.jar" + -jar my-service-name.jar" `); }); }); diff --git a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx index cba037d8939d8..936915250fcd1 100644 --- a/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx +++ b/x-pack/plugins/apm/public/tutorial/config_agent/index.tsx @@ -122,7 +122,6 @@ function TutorialConfigAgent({ } const hasFleetAgents = !!data.fleetAgents.length; - return ( <> {value}, + render: (_, { value }) => ( + + {value} + + ), }, { field: 'notes', diff --git a/x-pack/plugins/apm/server/routes/traces/route.ts b/x-pack/plugins/apm/server/routes/traces/route.ts index 4036495a18076..336e862bcd09d 100644 --- a/x-pack/plugins/apm/server/routes/traces/route.ts +++ b/x-pack/plugins/apm/server/routes/traces/route.ts @@ -169,14 +169,14 @@ const findTracesRoute = createApmServerRoute({ handler: async ( resources ): Promise<{ - samples: Array<{ traceId: string; transactionId: string }>; + traceSamples: Array<{ traceId: string; transactionId: string }>; }> => { const { start, end, environment, query, type } = resources.params.query; const setup = await setupRequest(resources); return { - samples: await getTraceSamplesByQuery({ + traceSamples: await getTraceSamplesByQuery({ setup, start, end, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/render.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/render.tsx index b34a7c02eb4b1..e53dce0a46886 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/render.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/render.tsx @@ -15,6 +15,7 @@ export const defaultHandlers: RendererHandlers = { getFilter: () => 'filter', getRenderMode: () => 'view', isSyncColorsEnabled: () => false, + isSyncCursorEnabled: () => true, isSyncTooltipsEnabled: () => false, isInteractive: () => true, onComplete: (fn) => undefined, diff --git a/x-pack/plugins/canvas/public/lib/create_handlers.ts b/x-pack/plugins/canvas/public/lib/create_handlers.ts index dbd542f18b537..374bdaff99721 100644 --- a/x-pack/plugins/canvas/public/lib/create_handlers.ts +++ b/x-pack/plugins/canvas/public/lib/create_handlers.ts @@ -28,6 +28,7 @@ export const createBaseHandlers = (): IInterpreterRenderHandlers => ({ getRenderMode: () => 'view', isSyncColorsEnabled: () => false, isSyncTooltipsEnabled: () => false, + isSyncCursorEnabled: () => true, isInteractive: () => true, getExecutionContext: () => undefined, }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/assignees.ts b/x-pack/plugins/cases/common/api/cases/user_actions/assignees.ts index e4b8b8aa1f6e9..4f218f5751960 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/assignees.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/assignees.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CaseAssigneesRt } from '../assignee'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const AssigneesUserActionPayloadRt = rt.type({ assignees: CaseAssigneesRt }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/comment.ts b/x-pack/plugins/cases/common/api/cases/user_actions/comment.ts index 652780b92f779..7826f450bd03b 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/comment.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/comment.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CommentRequestRt } from '../comment'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const CommentUserActionPayloadRt = rt.type({ comment: CommentRequestRt }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/connector.ts b/x-pack/plugins/cases/common/api/cases/user_actions/connector.ts index 90bea5926e97f..521ac99721e02 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/connector.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/connector.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CaseUserActionConnectorRt, CaseConnectorRt } from '../../connectors'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const ConnectorUserActionPayloadWithoutConnectorIdRt = rt.type({ connector: CaseUserActionConnectorRt, diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts b/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts index b4bc133ee73f3..60aa8132ff413 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { AssigneesUserActionPayloadRt } from './assignees'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; import { ConnectorUserActionPayloadRt, ConnectorUserActionPayloadWithoutConnectorIdRt, diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/delete_case.ts b/x-pack/plugins/cases/common/api/cases/user_actions/delete_case.ts index d024a8d10ce5f..f137b19616255 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/delete_case.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/delete_case.ts @@ -6,7 +6,8 @@ */ import * as rt from 'io-ts'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const DeleteCaseUserActionRt = rt.type({ type: rt.literal(ActionTypes.delete_case), diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/description.ts b/x-pack/plugins/cases/common/api/cases/user_actions/description.ts index db409e245cec1..89fc4627ae83e 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/description.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/description.ts @@ -6,7 +6,8 @@ */ import * as rt from 'io-ts'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const DescriptionUserActionPayloadRt = rt.type({ description: rt.string }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/index.ts b/x-pack/plugins/cases/common/api/cases/user_actions/index.ts index 6312e670533b9..ff8aea2fad9cd 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/index.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/index.ts @@ -7,12 +7,8 @@ import * as rt from 'io-ts'; -import { - ActionsRt, - UserActionCommonAttributesRt, - CaseUserActionSavedObjectIdsRt, - ActionTypesRt, -} from './common'; +import type { ActionsRt, ActionTypesRt } from './common'; +import { UserActionCommonAttributesRt, CaseUserActionSavedObjectIdsRt } from './common'; import { CreateCaseUserActionRt } from './create_case'; import { DescriptionUserActionRt } from './description'; import { CommentUserActionRt } from './comment'; diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/pushed.ts b/x-pack/plugins/cases/common/api/cases/user_actions/pushed.ts index c93fd1f6e4975..2ae500e32ec9f 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/pushed.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/pushed.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CaseUserActionExternalServiceRt, CaseExternalServiceBasicRt } from '../case'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const PushedUserActionPayloadWithoutConnectorIdRt = rt.type({ externalService: CaseUserActionExternalServiceRt, diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/settings.ts b/x-pack/plugins/cases/common/api/cases/user_actions/settings.ts index 0afbb6e1632d9..5094ec7680b1c 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/settings.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/settings.ts @@ -6,7 +6,8 @@ */ import * as rt from 'io-ts'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; import { SettingsRt } from '../case'; export const SettingsUserActionPayloadRt = rt.type({ settings: SettingsRt }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts b/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts index 2db5a0880dc09..c7ea0cb1e4b3f 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CaseSeverityRt } from '../case'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const SeverityUserActionPayloadRt = rt.type({ severity: CaseSeverityRt }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/status.ts b/x-pack/plugins/cases/common/api/cases/user_actions/status.ts index 09dceaa46b2de..97502433d69e0 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/status.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/status.ts @@ -7,7 +7,8 @@ import * as rt from 'io-ts'; import { CaseStatusRt } from '../status'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const StatusUserActionPayloadRt = rt.type({ status: CaseStatusRt }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/tags.ts b/x-pack/plugins/cases/common/api/cases/user_actions/tags.ts index 84f967ceda547..7da5798e85ebd 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/tags.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/tags.ts @@ -6,7 +6,8 @@ */ import * as rt from 'io-ts'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const TagsUserActionPayloadRt = rt.type({ tags: rt.array(rt.string) }); diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/title.ts b/x-pack/plugins/cases/common/api/cases/user_actions/title.ts index c92f07d1d7693..b0b54422488bd 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/title.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/title.ts @@ -6,7 +6,8 @@ */ import * as rt from 'io-ts'; -import { ActionTypes, UserActionWithAttributes } from './common'; +import type { UserActionWithAttributes } from './common'; +import { ActionTypes } from './common'; export const TitleUserActionPayloadRt = rt.type({ title: rt.string }); diff --git a/x-pack/plugins/cases/common/api/runtime_types.ts b/x-pack/plugins/cases/common/api/runtime_types.ts index 07ca40e89a2e2..b11828d3ae6b7 100644 --- a/x-pack/plugins/cases/common/api/runtime_types.ts +++ b/x-pack/plugins/cases/common/api/runtime_types.ts @@ -10,7 +10,7 @@ import { either, fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; -import { JsonArray, JsonObject, JsonValue } from '@kbn/utility-types'; +import type { JsonArray, JsonObject, JsonValue } from '@kbn/utility-types'; import { formatErrors } from '@kbn/securitysolution-io-ts-utils'; type ErrorFactory = (message: string) => Error; diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants.ts index 3c8f422d4eb7a..278cfc1050286 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ import { CASE_VIEW_PAGE_TABS } from './types'; -import { CasesFeaturesAllRequired } from './ui/types'; +import type { CasesFeaturesAllRequired } from './ui/types'; export const DEFAULT_DATE_FORMAT = 'dateFormat' as const; export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const; diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 65a7fec902f7b..a1cc7ad9eb91f 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -6,13 +6,13 @@ */ import type { ResolvedSimpleSavedObject } from '@kbn/core/public'; -import { +import type { CREATE_CASES_CAPABILITY, DELETE_CASES_CAPABILITY, READ_CASES_CAPABILITY, UPDATE_CASES_CAPABILITY, } from '..'; -import { +import type { CasePatchRequest, CaseStatuses, User, @@ -30,8 +30,8 @@ import { CommentResponseExternalReferenceType, CommentResponseTypePersistableState, } from '../api'; -import { PUSH_CASES_CAPABILITY } from '../constants'; -import { SnakeToCamelCase } from '../types'; +import type { PUSH_CASES_CAPABILITY } from '../constants'; +import type { SnakeToCamelCase } from '../types'; type DeepRequired = { [K in keyof T]: DeepRequired } & Required; diff --git a/x-pack/plugins/cases/common/utils/attachments.ts b/x-pack/plugins/cases/common/utils/attachments.ts index 75446ebedb0ed..e98df664ed2d4 100644 --- a/x-pack/plugins/cases/common/utils/attachments.ts +++ b/x-pack/plugins/cases/common/utils/attachments.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { +import type { CommentRequest, CommentRequestExternalReferenceType, - CommentType, CommentRequestPersistableStateType, } from '../api'; +import { CommentType } from '../api'; /** * A type narrowing function for external reference attachments. diff --git a/x-pack/plugins/cases/common/utils/markdown_plugins/lens/parser.ts b/x-pack/plugins/cases/common/utils/markdown_plugins/lens/parser.ts index 58ebfd76d5ac5..832876c5759ce 100644 --- a/x-pack/plugins/cases/common/utils/markdown_plugins/lens/parser.ts +++ b/x-pack/plugins/cases/common/utils/markdown_plugins/lens/parser.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { Plugin } from 'unified'; -import { RemarkTokenizer } from '@elastic/eui'; +import type { Plugin } from 'unified'; +import type { RemarkTokenizer } from '@elastic/eui'; import { LENS_ID } from './constants'; export const LensParser: Plugin = function () { diff --git a/x-pack/plugins/cases/common/utils/markdown_plugins/lens/serializer.ts b/x-pack/plugins/cases/common/utils/markdown_plugins/lens/serializer.ts index e99d9a8adc547..05f5516930978 100644 --- a/x-pack/plugins/cases/common/utils/markdown_plugins/lens/serializer.ts +++ b/x-pack/plugins/cases/common/utils/markdown_plugins/lens/serializer.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; import type { TimeRange } from '@kbn/es-query'; import { LENS_ID } from './constants'; diff --git a/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/parser.ts b/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/parser.ts index 0decdae8c7348..8b6f435780dac 100644 --- a/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/parser.ts +++ b/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/parser.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { Plugin } from 'unified'; -import { RemarkTokenizer } from '@elastic/eui'; +import type { Plugin } from 'unified'; +import type { RemarkTokenizer } from '@elastic/eui'; import * as i18n from './translations'; export const ID = 'timeline'; diff --git a/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/serializer.ts b/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/serializer.ts index b9448f93d95c3..e99baebfb0e95 100644 --- a/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/serializer.ts +++ b/x-pack/plugins/cases/common/utils/markdown_plugins/timeline/serializer.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Plugin } from 'unified'; +import type { Plugin } from 'unified'; export interface TimelineSerializerProps { match: string; } diff --git a/x-pack/plugins/cases/common/utils/markdown_plugins/utils.ts b/x-pack/plugins/cases/common/utils/markdown_plugins/utils.ts index 96d1f478c19aa..0d25bbd3a2765 100644 --- a/x-pack/plugins/cases/common/utils/markdown_plugins/utils.ts +++ b/x-pack/plugins/cases/common/utils/markdown_plugins/utils.ts @@ -11,7 +11,7 @@ import markdown from 'remark-parse'; import remarkStringify from 'remark-stringify'; import unified from 'unified'; -import { SerializableRecord } from '@kbn/utility-types'; +import type { SerializableRecord } from '@kbn/utility-types'; import type { TimeRange } from '@kbn/es-query'; import { LENS_ID, LensParser, LensSerializer } from './lens'; import { TimelineSerializer, TimelineParser } from './timeline'; diff --git a/x-pack/plugins/cases/common/utils/user_actions.ts b/x-pack/plugins/cases/common/utils/user_actions.ts index 3c9f819d4abe5..5c4420d26cd2a 100644 --- a/x-pack/plugins/cases/common/utils/user_actions.ts +++ b/x-pack/plugins/cases/common/utils/user_actions.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { - ActionTypes, +import type { CommentUserAction, ConnectorUserAction, CreateCaseUserAction, @@ -17,7 +16,8 @@ import { TitleUserAction, UserActionTypes, } from '../api'; -import { SnakeToCamelCase } from '../types'; +import { ActionTypes } from '../api'; +import type { SnakeToCamelCase } from '../types'; type SnakeCaseOrCamelCaseUserAction< T extends 'snakeCase' | 'camelCase', diff --git a/x-pack/plugins/cases/common/utils/validators.ts b/x-pack/plugins/cases/common/utils/validators.ts index 0003e3a91fd6f..2358ed0a9c2c3 100644 --- a/x-pack/plugins/cases/common/utils/validators.ts +++ b/x-pack/plugins/cases/common/utils/validators.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseAssignees } from '../api'; +import type { CaseAssignees } from '../api'; import { MAX_ASSIGNEES_PER_CASE } from '../constants'; export const isInvalidTag = (value: string) => value.trim() === ''; diff --git a/x-pack/plugins/cases/public/common/mock/test_providers.tsx b/x-pack/plugins/cases/public/common/mock/test_providers.tsx index 99ed0c274199c..b8c1b33507c3e 100644 --- a/x-pack/plugins/cases/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/cases/public/common/mock/test_providers.tsx @@ -17,11 +17,11 @@ import type { RenderOptions, RenderResult } from '@testing-library/react'; import { render as reactRender } from '@testing-library/react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { ILicense } from '@kbn/licensing-plugin/public'; +import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import type { CasesFeatures, CasesPermissions } from '../../../common/ui/types'; import { CasesProvider } from '../../components/cases_context'; import { createStartServicesMock } from '../lib/kibana/kibana_react.mock'; -import type { FieldHook } from '../shared_imports'; import type { StartServices } from '../../types'; import type { ReleasePhase } from '../../components/types'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; diff --git a/x-pack/plugins/cases/public/common/shared_imports.ts b/x-pack/plugins/cases/public/common/shared_imports.ts deleted file mode 100644 index 84c34a6186fa8..0000000000000 --- a/x-pack/plugins/cases/public/common/shared_imports.ts +++ /dev/null @@ -1,34 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export type { - FieldHook, - FieldValidateResponse, - FormData, - FormHook, - FormSchema, - ValidationError, - ValidationFunc, - FieldConfig, - ValidationConfig, -} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -export { - getUseField, - getFieldValidityAndErrorMessage, - FIELD_TYPES, - Form, - FormDataProvider, - UseField, - UseMultiFields, - useForm, - useFormContext, - useFormData, - VALIDATION_TYPES, -} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -export { Field, SelectField } from '@kbn/es-ui-shared-plugin/static/forms/components'; -export { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; -export type { ERROR_CODE } from '@kbn/es-ui-shared-plugin/static/forms/helpers/field_validators/types'; diff --git a/x-pack/plugins/cases/public/components/add_comment/index.tsx b/x-pack/plugins/cases/public/components/add_comment/index.tsx index 84715324bee92..dc5c1c48cfd9b 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -17,12 +17,17 @@ import { EuiButton, EuiFlexItem, EuiFlexGroup, EuiLoadingSpinner } from '@elasti import styled from 'styled-components'; import { isEmpty } from 'lodash'; +import { + Form, + useForm, + UseField, + useFormData, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { CommentType } from '../../../common/api'; import { useCreateAttachments } from '../../containers/use_create_attachments'; import type { Case } from '../../containers/types'; import type { EuiMarkdownEditorRef } from '../markdown_editor'; import { MarkdownEditorForm } from '../markdown_editor'; -import { Form, useForm, UseField, useFormData } from '../../common/shared_imports'; import * as i18n from './translations'; import type { AddCommentFormSchema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/add_comment/schema.tsx b/x-pack/plugins/cases/public/components/add_comment/schema.tsx index 7f8da37aeedc6..5df5769ef62ab 100644 --- a/x-pack/plugins/cases/public/components/add_comment/schema.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/schema.tsx @@ -5,9 +5,10 @@ * 2.0. */ +import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { CommentRequestUserType } from '../../../common/api'; -import type { FormSchema } from '../../common/shared_imports'; -import { FIELD_TYPES, fieldValidators } from '../../common/shared_imports'; import * as i18n from './translations'; const { emptyField } = fieldValidators; diff --git a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx index 3a3a01cc49e94..2f8567d14f08d 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx @@ -18,15 +18,15 @@ import { } from '@elastic/eui'; import styled, { css } from 'styled-components'; import { isEqual } from 'lodash/fp'; -import * as i18n from '../../tags/translations'; -import type { FormSchema } from '../../../common/shared_imports'; +import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Form, FormDataProvider, useForm, getUseField, - Field, -} from '../../../common/shared_imports'; +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; +import * as i18n from '../../tags/translations'; import { useGetTags } from '../../../containers/use_get_tags'; import { Tags } from '../../tags/tags'; import { useCasesContext } from '../../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/connector_selector/form.test.tsx b/x-pack/plugins/cases/public/components/connector_selector/form.test.tsx index 139d8c48692a0..8729c13be1487 100644 --- a/x-pack/plugins/cases/public/components/connector_selector/form.test.tsx +++ b/x-pack/plugins/cases/public/components/connector_selector/form.test.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import type { FormHook } from '../../common/shared_imports'; -import { UseField, Form, useForm } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { UseField, Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { ConnectorSelector } from './form'; import { connectorsMock } from '../../containers/mock'; import { getFormMock } from '../__mock__/form'; diff --git a/x-pack/plugins/cases/public/components/connector_selector/form.tsx b/x-pack/plugins/cases/public/components/connector_selector/form.tsx index 6f9f416e69037..b588182050d6a 100644 --- a/x-pack/plugins/cases/public/components/connector_selector/form.tsx +++ b/x-pack/plugins/cases/public/components/connector_selector/form.tsx @@ -10,8 +10,8 @@ import { isEmpty } from 'lodash/fp'; import { EuiFormRow } from '@elastic/eui'; import styled from 'styled-components'; -import type { FieldHook } from '../../common/shared_imports'; -import { getFieldValidityAndErrorMessage } from '../../common/shared_imports'; +import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { getFieldValidityAndErrorMessage } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { ConnectorsDropdown } from '../configure_cases/connectors_dropdown'; import type { ActionConnector } from '../../../common/api'; diff --git a/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts b/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts index 8480350841b0e..eddac63223de8 100644 --- a/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts +++ b/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { ValidationConfig } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { SwimlaneConnectorType } from '../../../../common/api'; -import type { ValidationConfig } from '../../../common/shared_imports'; import type { CaseActionConnector } from '../../types'; const casesRequiredFields = [ diff --git a/x-pack/plugins/cases/public/components/create/assignees.test.tsx b/x-pack/plugins/cases/public/components/create/assignees.test.tsx index 97ee74ad76831..9a32ab5f1ffd9 100644 --- a/x-pack/plugins/cases/public/components/create/assignees.test.tsx +++ b/x-pack/plugins/cases/public/components/create/assignees.test.tsx @@ -10,8 +10,8 @@ import userEvent from '@testing-library/user-event'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { userProfiles } from '../../containers/user_profiles/api.mock'; import { Assignees } from './assignees'; import type { FormProps } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/assignees.tsx b/x-pack/plugins/cases/public/components/create/assignees.tsx index 1b5577bd87469..6066957722358 100644 --- a/x-pack/plugins/cases/public/components/create/assignees.tsx +++ b/x-pack/plugins/cases/public/components/create/assignees.tsx @@ -17,10 +17,13 @@ import { } from '@elastic/eui'; import type { UserProfileWithAvatar, UserProfile } from '@kbn/user-profile-components'; import { UserAvatar, getUserDisplayName } from '@kbn/user-profile-components'; +import type { FieldConfig, FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { + UseField, + getFieldValidityAndErrorMessage, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { MAX_ASSIGNEES_PER_CASE } from '../../../common/constants'; import type { CaseAssignees } from '../../../common/api'; -import type { FieldConfig, FieldHook } from '../../common/shared_imports'; -import { UseField, getFieldValidityAndErrorMessage } from '../../common/shared_imports'; import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles'; import { useCasesContext } from '../cases_context/use_cases_context'; import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; diff --git a/x-pack/plugins/cases/public/components/create/connector.test.tsx b/x-pack/plugins/cases/public/components/create/connector.test.tsx index 1fc99cf30ab75..037293802201f 100644 --- a/x-pack/plugins/cases/public/components/create/connector.test.tsx +++ b/x-pack/plugins/cases/public/components/create/connector.test.tsx @@ -11,8 +11,8 @@ import { act, waitFor } from '@testing-library/react'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { connectorsMock } from '../../containers/mock'; import { Connector } from './connector'; import { useGetIncidentTypes } from '../connectors/resilient/use_get_incident_types'; diff --git a/x-pack/plugins/cases/public/components/create/connector.tsx b/x-pack/plugins/cases/public/components/create/connector.tsx index 102b8ec73d1b0..0431d31ced1e0 100644 --- a/x-pack/plugins/cases/public/components/create/connector.tsx +++ b/x-pack/plugins/cases/public/components/create/connector.tsx @@ -8,9 +8,13 @@ import React, { memo, useCallback, useMemo, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import type { FieldHook, FieldConfig } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { + UseField, + useFormData, + useFormContext, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { ActionConnector } from '../../../common/api'; -import type { FieldHook, FieldConfig } from '../../common/shared_imports'; -import { UseField, useFormData, useFormContext } from '../../common/shared_imports'; import { ConnectorSelector } from '../connector_selector/form'; import { ConnectorFieldsForm } from '../connectors/fields_form'; import type { FormProps } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/description.test.tsx b/x-pack/plugins/cases/public/components/create/description.test.tsx index d95fade009f3d..3e9adb8961cc2 100644 --- a/x-pack/plugins/cases/public/components/create/description.test.tsx +++ b/x-pack/plugins/cases/public/components/create/description.test.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; import userEvent, { specialChars } from '@testing-library/user-event'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Description } from './description'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/description.tsx b/x-pack/plugins/cases/public/components/create/description.tsx index 6c9792684a126..437ff5c3751c1 100644 --- a/x-pack/plugins/cases/public/components/create/description.tsx +++ b/x-pack/plugins/cases/public/components/create/description.tsx @@ -6,8 +6,12 @@ */ import React, { memo, useEffect, useRef } from 'react'; +import { + UseField, + useFormContext, + useFormData, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { MarkdownEditorForm } from '../markdown_editor'; -import { UseField, useFormContext, useFormData } from '../../common/shared_imports'; import { useLensDraftComment } from '../markdown_editor/plugins/lens/use_lens_draft_comment'; import { ID as LensPluginId } from '../markdown_editor/plugins/lens/constants'; diff --git a/x-pack/plugins/cases/public/components/create/form.test.tsx b/x-pack/plugins/cases/public/components/create/form.test.tsx index 3316134f7762e..ddc65f443bdb3 100644 --- a/x-pack/plugins/cases/public/components/create/form.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form.test.tsx @@ -11,8 +11,8 @@ import { act, render } from '@testing-library/react'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { NONE_CONNECTOR_ID } from '../../../common/api'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { connectorsMock } from '../../containers/mock'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 32fff2048685d..e1a0c4f3b1cea 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -15,7 +15,7 @@ import { } from '@elastic/eui'; import styled, { css } from 'styled-components'; -import { useFormContext } from '../../common/shared_imports'; +import { useFormContext } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Title } from './title'; import { Description, fieldName as descriptionFieldName } from './description'; diff --git a/x-pack/plugins/cases/public/components/create/form_context.tsx b/x-pack/plugins/cases/public/components/create/form_context.tsx index 1e6cfaafe4eeb..fdce32c38c880 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.tsx @@ -6,9 +6,9 @@ */ import React, { useCallback, useMemo } from 'react'; +import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { FormProps } from './schema'; import { schema } from './schema'; -import { Form, useForm } from '../../common/shared_imports'; import { getNoneConnector, normalizeActionConnector } from '../configure_cases/utils'; import { usePostCase } from '../../containers/use_post_case'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index a1ffd7b3ebd6b..386b64f04bd1c 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -7,7 +7,8 @@ import React from 'react'; -import { Field, getUseField } from '../../common/shared_imports'; +import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; +import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import * as i18n from './translations'; import type { CreateCaseFormProps } from './form'; import { CreateCaseForm } from './form'; diff --git a/x-pack/plugins/cases/public/components/create/owner_selector.test.tsx b/x-pack/plugins/cases/public/components/create/owner_selector.test.tsx index 25f0f9ba0faaa..cd9515edbd28c 100644 --- a/x-pack/plugins/cases/public/components/create/owner_selector.test.tsx +++ b/x-pack/plugins/cases/public/components/create/owner_selector.test.tsx @@ -11,8 +11,8 @@ import { act, waitFor } from '@testing-library/react'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { OBSERVABILITY_OWNER } from '../../../common/constants'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { CreateCaseOwnerSelector } from './owner_selector'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/owner_selector.tsx b/x-pack/plugins/cases/public/components/create/owner_selector.tsx index e572e7c9f9ca5..440fcffcbb5d8 100644 --- a/x-pack/plugins/cases/public/components/create/owner_selector.tsx +++ b/x-pack/plugins/cases/public/components/create/owner_selector.tsx @@ -16,13 +16,15 @@ import { EuiKeyPadMenuItem, useGeneratedHtmlId, } from '@elastic/eui'; - +import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { + getFieldValidityAndErrorMessage, + UseField, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { OWNER_INFO } from '../../../common/constants'; -import type { FieldHook } from '../../common/shared_imports'; -import { getFieldValidityAndErrorMessage, UseField } from '../../common/shared_imports'; import * as i18n from './translations'; interface OwnerSelectorProps { diff --git a/x-pack/plugins/cases/public/components/create/schema.tsx b/x-pack/plugins/cases/public/components/create/schema.tsx index 30dc762143ae3..f80c4e52945bb 100644 --- a/x-pack/plugins/cases/public/components/create/schema.tsx +++ b/x-pack/plugins/cases/public/components/create/schema.tsx @@ -5,11 +5,12 @@ * 2.0. */ +import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { FIELD_TYPES, VALIDATION_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { CasePostRequest, ConnectorTypeFields } from '../../../common/api'; import { isInvalidTag } from '../../../common/utils/validators'; import { MAX_TITLE_LENGTH } from '../../../common/constants'; -import type { FormSchema } from '../../common/shared_imports'; -import { FIELD_TYPES, fieldValidators, VALIDATION_TYPES } from '../../common/shared_imports'; import * as i18n from './translations'; import { OptionalFieldLabel } from './optional_field_label'; diff --git a/x-pack/plugins/cases/public/components/create/severity.test.tsx b/x-pack/plugins/cases/public/components/create/severity.test.tsx index 5d80028817a83..b8a5b446b89f8 100644 --- a/x-pack/plugins/cases/public/components/create/severity.test.tsx +++ b/x-pack/plugins/cases/public/components/create/severity.test.tsx @@ -9,8 +9,8 @@ import { CaseSeverity } from '../../../common/api'; import React from 'react'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; -import type { FormHook } from '../../common/shared_imports'; -import { Form, useForm } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Severity } from './severity'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/severity.tsx b/x-pack/plugins/cases/public/components/create/severity.tsx index 730eab5d77ac6..3e090272162e8 100644 --- a/x-pack/plugins/cases/public/components/create/severity.tsx +++ b/x-pack/plugins/cases/public/components/create/severity.tsx @@ -7,8 +7,12 @@ import { EuiFormRow } from '@elastic/eui'; import React, { memo } from 'react'; +import { + UseField, + useFormContext, + useFormData, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { CaseSeverity } from '../../../common/api'; -import { UseField, useFormContext, useFormData } from '../../common/shared_imports'; import { SeveritySelector } from '../severity/selector'; import { SEVERITY_TITLE } from '../severity/translations'; diff --git a/x-pack/plugins/cases/public/components/create/submit_button.test.tsx b/x-pack/plugins/cases/public/components/create/submit_button.test.tsx index b703eb703d720..95dc8d783ac3e 100644 --- a/x-pack/plugins/cases/public/components/create/submit_button.test.tsx +++ b/x-pack/plugins/cases/public/components/create/submit_button.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; -import { useForm, Form } from '../../common/shared_imports'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { SubmitCaseButton } from './submit_button'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/submit_button.tsx b/x-pack/plugins/cases/public/components/create/submit_button.tsx index 9f984b236ca69..2c3ecd563df73 100644 --- a/x-pack/plugins/cases/public/components/create/submit_button.tsx +++ b/x-pack/plugins/cases/public/components/create/submit_button.tsx @@ -8,7 +8,7 @@ import React, { memo } from 'react'; import { EuiButton } from '@elastic/eui'; -import { useFormContext } from '../../common/shared_imports'; +import { useFormContext } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import * as i18n from './translations'; const SubmitCaseButtonComponent: React.FC = () => { diff --git a/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.test.tsx b/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.test.tsx index 28abe40607c72..aa5d80e82a34f 100644 --- a/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.test.tsx +++ b/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.test.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { SyncAlertsToggle } from './sync_alerts_toggle'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.tsx b/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.tsx index bed8e6d18f5e3..1a189de3e17ec 100644 --- a/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.tsx +++ b/x-pack/plugins/cases/public/components/create/sync_alerts_toggle.tsx @@ -6,7 +6,8 @@ */ import React, { memo } from 'react'; -import { Field, getUseField, useFormData } from '../../common/shared_imports'; +import { getUseField, useFormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; import * as i18n from './translations'; const CommonUseField = getUseField({ component: Field }); diff --git a/x-pack/plugins/cases/public/components/create/tags.test.tsx b/x-pack/plugins/cases/public/components/create/tags.test.tsx index 9e84955c3a07e..653f32d09f600 100644 --- a/x-pack/plugins/cases/public/components/create/tags.test.tsx +++ b/x-pack/plugins/cases/public/components/create/tags.test.tsx @@ -11,8 +11,8 @@ import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; import { waitFor } from '@testing-library/react'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Tags } from './tags'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/tags.tsx b/x-pack/plugins/cases/public/components/create/tags.tsx index 11dac39bba75b..6bae6015e769b 100644 --- a/x-pack/plugins/cases/public/components/create/tags.tsx +++ b/x-pack/plugins/cases/public/components/create/tags.tsx @@ -7,7 +7,8 @@ import React, { memo, useMemo } from 'react'; -import { Field, getUseField } from '../../common/shared_imports'; +import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; import { useGetTags } from '../../containers/use_get_tags'; const CommonUseField = getUseField({ component: Field }); diff --git a/x-pack/plugins/cases/public/components/create/title.test.tsx b/x-pack/plugins/cases/public/components/create/title.test.tsx index 37952ba530842..793a868f8a1cb 100644 --- a/x-pack/plugins/cases/public/components/create/title.test.tsx +++ b/x-pack/plugins/cases/public/components/create/title.test.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { act } from '@testing-library/react'; -import type { FormHook } from '../../common/shared_imports'; -import { useForm, Form } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { useForm, Form } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { Title } from './title'; import type { FormProps } from './schema'; import { schema } from './schema'; diff --git a/x-pack/plugins/cases/public/components/create/title.tsx b/x-pack/plugins/cases/public/components/create/title.tsx index ae8f517173132..35de4c7a41ccb 100644 --- a/x-pack/plugins/cases/public/components/create/title.tsx +++ b/x-pack/plugins/cases/public/components/create/title.tsx @@ -6,8 +6,8 @@ */ import React, { memo } from 'react'; -import { Field, getUseField } from '../../common/shared_imports'; - +import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; const CommonUseField = getUseField({ component: Field }); interface Props { diff --git a/x-pack/plugins/cases/public/components/edit_connector/index.tsx b/x-pack/plugins/cases/public/components/edit_connector/index.tsx index 7be868fa5d625..7fa73395ba8a1 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/index.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/index.tsx @@ -19,8 +19,8 @@ import { import styled from 'styled-components'; import { isEmpty, noop } from 'lodash/fp'; -import type { FieldConfig } from '../../common/shared_imports'; -import { Form, UseField, useForm } from '../../common/shared_imports'; +import type { FieldConfig } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Form, UseField, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { Case } from '../../../common/ui/types'; import type { ActionConnector, ConnectorTypeFields } from '../../../common/api'; import { NONE_CONNECTOR_ID } from '../../../common/api'; diff --git a/x-pack/plugins/cases/public/components/edit_connector/schema.tsx b/x-pack/plugins/cases/public/components/edit_connector/schema.tsx index 0ff191fff5bda..27eecc485ea42 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/schema.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/schema.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import type { FormSchema } from '../../common/shared_imports'; -import { FIELD_TYPES } from '../../common/shared_imports'; +import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; export interface FormProps { connectorId: string; diff --git a/x-pack/plugins/cases/public/components/insert_timeline/index.test.tsx b/x-pack/plugins/cases/public/components/insert_timeline/index.test.tsx index 931cf3255c5a5..d616ae71bd826 100644 --- a/x-pack/plugins/cases/public/components/insert_timeline/index.test.tsx +++ b/x-pack/plugins/cases/public/components/insert_timeline/index.test.tsx @@ -10,8 +10,8 @@ import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; import { TestProviders } from '../../common/mock'; -import type { FormHook } from '../../common/shared_imports'; -import { Form, useForm } from '../../common/shared_imports'; +import type { FormHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { Form, useForm } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { timelineIntegrationMock } from '../__mock__/timeline'; import { getFormMock } from '../__mock__/form'; diff --git a/x-pack/plugins/cases/public/components/insert_timeline/index.tsx b/x-pack/plugins/cases/public/components/insert_timeline/index.tsx index 62b8ad7155581..0a1e6c02b22e6 100644 --- a/x-pack/plugins/cases/public/components/insert_timeline/index.tsx +++ b/x-pack/plugins/cases/public/components/insert_timeline/index.tsx @@ -6,7 +6,7 @@ */ import { useCallback } from 'react'; -import { useFormContext } from '../../common/shared_imports'; +import { useFormContext } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { useTimelineContext } from '../timeline_context/use_timeline_context'; type InsertFields = 'comment' | 'description'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/eui_form.tsx b/x-pack/plugins/cases/public/components/markdown_editor/eui_form.tsx index 2884816a091a3..ff073f7eef08a 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/eui_form.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/eui_form.tsx @@ -9,8 +9,8 @@ import React, { forwardRef, useMemo } from 'react'; import styled from 'styled-components'; import type { EuiMarkdownEditorProps } from '@elastic/eui'; import { EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; -import type { FieldHook } from '../../common/shared_imports'; -import { getFieldValidityAndErrorMessage } from '../../common/shared_imports'; +import type { FieldHook } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { getFieldValidityAndErrorMessage } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import type { MarkdownEditorRef } from './editor'; import { MarkdownEditor } from './editor'; import { CommentEditorContext } from './context'; diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx index 784e163fa963d..b2b7443e001e8 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx @@ -9,8 +9,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/e import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from 'react'; import styled from 'styled-components'; +import { Form, useForm, UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import * as i18n from '../case_view/translations'; -import { Form, useForm, UseField } from '../../common/shared_imports'; import type { Content } from './schema'; import { schema } from './schema'; import { MarkdownRenderer, MarkdownEditorForm } from '../markdown_editor'; diff --git a/x-pack/plugins/cases/public/components/user_actions/schema.ts b/x-pack/plugins/cases/public/components/user_actions/schema.ts index ecc1f981829b0..8c47b700adeb5 100644 --- a/x-pack/plugins/cases/public/components/user_actions/schema.ts +++ b/x-pack/plugins/cases/public/components/user_actions/schema.ts @@ -5,8 +5,9 @@ * 2.0. */ -import type { FormSchema } from '../../common/shared_imports'; -import { FIELD_TYPES, fieldValidators } from '../../common/shared_imports'; +import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import * as i18n from '../../common/translations'; const { emptyField } = fieldValidators; diff --git a/x-pack/plugins/cases/public/components/utils.ts b/x-pack/plugins/cases/public/components/utils.ts index 45b2247b7bcac..1a5f8134563ff 100644 --- a/x-pack/plugins/cases/public/components/utils.ts +++ b/x-pack/plugins/cases/public/components/utils.ts @@ -6,8 +6,11 @@ */ import type { IconType } from '@elastic/eui'; +import type { + FieldConfig, + ValidationConfig, +} from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { ConnectorTypes } from '../../common/api'; -import type { FieldConfig, ValidationConfig } from '../common/shared_imports'; import type { CasesPluginStart } from '../types'; import { connectorValidator as swimlaneConnectorValidator } from './connectors/swimlane/validator'; import type { CaseActionConnector } from './types'; diff --git a/x-pack/plugins/cases/server/attachment_framework/external_reference_registry.ts b/x-pack/plugins/cases/server/attachment_framework/external_reference_registry.ts index 131f91868e0d9..b60992f2faa5a 100644 --- a/x-pack/plugins/cases/server/attachment_framework/external_reference_registry.ts +++ b/x-pack/plugins/cases/server/attachment_framework/external_reference_registry.ts @@ -6,7 +6,7 @@ */ import { AttachmentTypeRegistry } from '../../common/registry'; -import { ExternalReferenceAttachmentType } from './types'; +import type { ExternalReferenceAttachmentType } from './types'; export class ExternalReferenceAttachmentTypeRegistry extends AttachmentTypeRegistry { constructor() { diff --git a/x-pack/plugins/cases/server/attachment_framework/mocks.ts b/x-pack/plugins/cases/server/attachment_framework/mocks.ts index 9de42dc86588f..d0c6fdf037f2b 100644 --- a/x-pack/plugins/cases/server/attachment_framework/mocks.ts +++ b/x-pack/plugins/cases/server/attachment_framework/mocks.ts @@ -7,15 +7,15 @@ import { omit } from 'lodash'; import { CommentType, SECURITY_SOLUTION_OWNER } from '../../common'; -import { +import type { AttributesTypeExternalReferenceNoSO, AttributesTypeExternalReferenceSO, AttributesTypePersistableState, CommentRequestPersistableStateType, - ExternalReferenceStorageType, } from '../../common/api'; +import { ExternalReferenceStorageType } from '../../common/api'; import { PersistableStateAttachmentTypeRegistry } from './persistable_state_registry'; -import { PersistableStateAttachmentTypeSetup, PersistableStateAttachmentState } from './types'; +import type { PersistableStateAttachmentTypeSetup, PersistableStateAttachmentState } from './types'; export const getPersistableAttachment = (): PersistableStateAttachmentTypeSetup => ({ id: '.test', diff --git a/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts b/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts index 5ca965a7da726..c3133a664d965 100644 --- a/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts +++ b/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts @@ -7,7 +7,7 @@ import { identity } from 'lodash'; import { AttachmentTypeRegistry } from '../../common/registry'; -import { PersistableStateAttachmentType, PersistableStateAttachmentTypeSetup } from './types'; +import type { PersistableStateAttachmentType, PersistableStateAttachmentTypeSetup } from './types'; export class PersistableStateAttachmentTypeRegistry extends AttachmentTypeRegistry { constructor() { diff --git a/x-pack/plugins/cases/server/attachment_framework/so_references.ts b/x-pack/plugins/cases/server/attachment_framework/so_references.ts index f6f2435235289..c8ad18e39a7cc 100644 --- a/x-pack/plugins/cases/server/attachment_framework/so_references.ts +++ b/x-pack/plugins/cases/server/attachment_framework/so_references.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { SavedObjectReference } from '@kbn/core/types'; +import type { SavedObjectReference } from '@kbn/core/types'; import { isCommentRequestTypePersistableState } from '../../common/utils/attachments'; -import { CommentRequest, CommentRequestPersistableStateType } from '../../common/api'; -import { PersistableStateAttachmentTypeRegistry } from './persistable_state_registry'; +import type { CommentRequest, CommentRequestPersistableStateType } from '../../common/api'; +import type { PersistableStateAttachmentTypeRegistry } from './persistable_state_registry'; interface SavedObjectAttributesAndReferences { state: CommentRequestPersistableStateType; diff --git a/x-pack/plugins/cases/server/attachment_framework/types.ts b/x-pack/plugins/cases/server/attachment_framework/types.ts index 50d9952a807ad..4b47332c124f5 100644 --- a/x-pack/plugins/cases/server/attachment_framework/types.ts +++ b/x-pack/plugins/cases/server/attachment_framework/types.ts @@ -6,7 +6,7 @@ */ import type { PersistableState, PersistableStateDefinition } from '@kbn/kibana-utils-plugin/common'; -import { CommentRequestPersistableStateType } from '../../common/api'; +import type { CommentRequestPersistableStateType } from '../../common/api'; export type PersistableStateAttachmentState = Pick< CommentRequestPersistableStateType, diff --git a/x-pack/plugins/cases/server/authorization/audit_logger.test.ts b/x-pack/plugins/cases/server/authorization/audit_logger.test.ts index d06881b8c230d..b2bbf1f4afac3 100644 --- a/x-pack/plugins/cases/server/authorization/audit_logger.test.ts +++ b/x-pack/plugins/cases/server/authorization/audit_logger.test.ts @@ -8,7 +8,7 @@ import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; import { Operations } from '.'; import { AuthorizationAuditLogger } from './audit_logger'; -import { ReadOperations } from './types'; +import type { ReadOperations } from './types'; describe('audit_logger', () => { it('creates a failure message without any owners', () => { diff --git a/x-pack/plugins/cases/server/authorization/audit_logger.ts b/x-pack/plugins/cases/server/authorization/audit_logger.ts index e0f2ae710e6f6..8a415e1b69559 100644 --- a/x-pack/plugins/cases/server/authorization/audit_logger.ts +++ b/x-pack/plugins/cases/server/authorization/audit_logger.ts @@ -5,10 +5,11 @@ * 2.0. */ -import { EcsEventOutcome } from '@kbn/core/server'; -import { AuditEvent, AuditLogger } from '@kbn/security-plugin/server'; -import { DATABASE_CATEGORY, ECS_OUTCOMES, isWriteOperation, OperationDetails } from '.'; -import { OwnerEntity } from './types'; +import type { EcsEventOutcome } from '@kbn/core/server'; +import type { AuditEvent, AuditLogger } from '@kbn/security-plugin/server'; +import type { OperationDetails } from '.'; +import { DATABASE_CATEGORY, ECS_OUTCOMES, isWriteOperation } from '.'; +import type { OwnerEntity } from './types'; interface CreateAuditMsgParams { operation: OperationDetails; diff --git a/x-pack/plugins/cases/server/authorization/authorization.test.ts b/x-pack/plugins/cases/server/authorization/authorization.test.ts index 3e59617856c2b..0483489d6c8a2 100644 --- a/x-pack/plugins/cases/server/authorization/authorization.test.ts +++ b/x-pack/plugins/cases/server/authorization/authorization.test.ts @@ -9,14 +9,14 @@ import { securityMock } from '@kbn/security-plugin/server/mocks'; import { httpServerMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { featuresPluginMock } from '@kbn/features-plugin/server/mocks'; import { Authorization, Operations } from '.'; -import { Space, SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { Space, SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { spacesMock } from '@kbn/spaces-plugin/server/mocks'; import { AuthorizationAuditLogger } from './audit_logger'; -import { KibanaRequest } from '@kbn/core/server'; -import { KibanaFeature } from '@kbn/features-plugin/common'; -import { AuditLogger, SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { KibanaRequest } from '@kbn/core/server'; +import type { KibanaFeature } from '@kbn/features-plugin/common'; +import type { AuditLogger, SecurityPluginStart } from '@kbn/security-plugin/server'; import { auditLoggerMock } from '@kbn/security-plugin/server/audit/mocks'; -import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; +import type { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; const createSpacesDisabledFeaturesMock = (disabledFeatures: string[] = []) => { const spacesStart: jest.Mocked = spacesMock.createStart(); diff --git a/x-pack/plugins/cases/server/authorization/authorization.ts b/x-pack/plugins/cases/server/authorization/authorization.ts index 3f2cb9196d8e0..f3b3b871810b4 100644 --- a/x-pack/plugins/cases/server/authorization/authorization.ts +++ b/x-pack/plugins/cases/server/authorization/authorization.ts @@ -5,14 +5,15 @@ * 2.0. */ -import { KibanaRequest, Logger } from '@kbn/core/server'; +import type { KibanaRequest, Logger } from '@kbn/core/server'; import Boom from '@hapi/boom'; -import { SecurityPluginStart } from '@kbn/security-plugin/server'; -import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; -import { Space, SpacesPluginStart } from '@kbn/spaces-plugin/server'; -import { AuthFilterHelpers, OwnerEntity } from './types'; +import type { SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; +import type { Space, SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { AuthFilterHelpers, OwnerEntity } from './types'; import { getOwnersFilter } from './utils'; -import { AuthorizationAuditLogger, OperationDetails } from '.'; +import type { OperationDetails } from '.'; +import { AuthorizationAuditLogger } from '.'; import { createCaseError } from '../common/error'; /** diff --git a/x-pack/plugins/cases/server/authorization/index.test.ts b/x-pack/plugins/cases/server/authorization/index.test.ts index df74b230c6435..8ed6deae95dac 100644 --- a/x-pack/plugins/cases/server/authorization/index.test.ts +++ b/x-pack/plugins/cases/server/authorization/index.test.ts @@ -6,7 +6,7 @@ */ import { isWriteOperation, Operations } from '.'; -import { OperationDetails } from './types'; +import type { OperationDetails } from './types'; describe('index tests', () => { it('should identify a write operation', () => { diff --git a/x-pack/plugins/cases/server/authorization/index.ts b/x-pack/plugins/cases/server/authorization/index.ts index 122eb90f44dc1..44e8a50c931d8 100644 --- a/x-pack/plugins/cases/server/authorization/index.ts +++ b/x-pack/plugins/cases/server/authorization/index.ts @@ -5,15 +5,16 @@ * 2.0. */ -import { EcsEventCategory, EcsEventOutcome, EcsEventType } from '@kbn/core/server'; -import { CasesSupportedOperations } from '@kbn/security-plugin/server'; +import type { EcsEventCategory, EcsEventOutcome, EcsEventType } from '@kbn/core/server'; +import type { CasesSupportedOperations } from '@kbn/security-plugin/server'; import { CASE_COMMENT_SAVED_OBJECT, CASE_CONFIGURE_SAVED_OBJECT, CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, } from '../../common/constants'; -import { Verbs, ReadOperations, WriteOperations, OperationDetails } from './types'; +import type { Verbs, OperationDetails } from './types'; +import { ReadOperations, WriteOperations } from './types'; export * from './authorization'; export * from './audit_logger'; diff --git a/x-pack/plugins/cases/server/authorization/mock.ts b/x-pack/plugins/cases/server/authorization/mock.ts index 555d3ac7a9991..2e94915df39b1 100644 --- a/x-pack/plugins/cases/server/authorization/mock.ts +++ b/x-pack/plugins/cases/server/authorization/mock.ts @@ -6,7 +6,7 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { Authorization } from './authorization'; +import type { Authorization } from './authorization'; type Schema = PublicMethodsOf; export type AuthorizationMock = jest.Mocked; diff --git a/x-pack/plugins/cases/server/authorization/types.ts b/x-pack/plugins/cases/server/authorization/types.ts index 58418efb6b25b..c27070cb74805 100644 --- a/x-pack/plugins/cases/server/authorization/types.ts +++ b/x-pack/plugins/cases/server/authorization/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { EcsEventType } from '@kbn/core/server'; +import type { EcsEventType } from '@kbn/core/server'; import type { KueryNode } from '@kbn/es-query'; -import { CasesSupportedOperations } from '@kbn/security-plugin/server'; +import type { CasesSupportedOperations } from '@kbn/security-plugin/server'; /** * The tenses for describing the action performed by a API route diff --git a/x-pack/plugins/cases/server/authorization/utils.ts b/x-pack/plugins/cases/server/authorization/utils.ts index d33d3dd99a47f..3717140a7c18b 100644 --- a/x-pack/plugins/cases/server/authorization/utils.ts +++ b/x-pack/plugins/cases/server/authorization/utils.ts @@ -6,7 +6,8 @@ */ import { remove, uniq } from 'lodash'; -import { nodeBuilder, KueryNode } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; +import { nodeBuilder } from '@kbn/es-query'; import { OWNER_FIELD } from '../../common/api'; export const getOwnersFilter = ( diff --git a/x-pack/plugins/cases/server/client/alerts/get.test.ts b/x-pack/plugins/cases/server/client/alerts/get.test.ts index 41c6a665f74e7..8659a190ef7a9 100644 --- a/x-pack/plugins/cases/server/client/alerts/get.test.ts +++ b/x-pack/plugins/cases/server/client/alerts/get.test.ts @@ -7,7 +7,7 @@ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { AlertService } from '../../services'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { getAlerts } from './get'; describe('getAlerts', () => { diff --git a/x-pack/plugins/cases/server/client/alerts/get.ts b/x-pack/plugins/cases/server/client/alerts/get.ts index acc0f5e895cdc..dead5d73fbf3d 100644 --- a/x-pack/plugins/cases/server/client/alerts/get.ts +++ b/x-pack/plugins/cases/server/client/alerts/get.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { MgetResponseItem, GetGetResult } from '@elastic/elasticsearch/lib/api/types'; -import { CasesClientGetAlertsResponse } from './types'; -import { CasesClientArgs } from '..'; -import { AlertInfo } from '../../common/types'; -import { Alert } from '../../services/alerts'; +import type { MgetResponseItem, GetGetResult } from '@elastic/elasticsearch/lib/api/types'; +import type { CasesClientGetAlertsResponse } from './types'; +import type { CasesClientArgs } from '..'; +import type { AlertInfo } from '../../common/types'; +import type { Alert } from '../../services/alerts'; function isAlert( doc?: MgetResponseItem diff --git a/x-pack/plugins/cases/server/client/alerts/types.ts b/x-pack/plugins/cases/server/client/alerts/types.ts index cba18cc26e8b7..23eef9850be24 100644 --- a/x-pack/plugins/cases/server/client/alerts/types.ts +++ b/x-pack/plugins/cases/server/client/alerts/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { CaseStatuses } from '../../../common/api'; -import { AlertInfo } from '../../common/types'; +import type { CaseStatuses } from '../../../common/api'; +import type { AlertInfo } from '../../common/types'; interface Alert { id: string; diff --git a/x-pack/plugins/cases/server/client/attachments/add.ts b/x-pack/plugins/cases/server/client/attachments/add.ts index 979828c35ecdd..333d5bfdb6771 100644 --- a/x-pack/plugins/cases/server/client/attachments/add.ts +++ b/x-pack/plugins/cases/server/client/attachments/add.ts @@ -16,11 +16,12 @@ import { isCommentRequestTypeExternalReference, isCommentRequestTypePersistableState, } from '../../../common/utils/attachments'; -import { CaseResponse, CommentRequest, CommentRequestRt, throwErrors } from '../../../common/api'; +import type { CaseResponse, CommentRequest } from '../../../common/api'; +import { CommentRequestRt, throwErrors } from '../../../common/api'; import { CaseCommentModel } from '../../common/models'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { decodeCommentRequest } from '../utils'; import { Operations } from '../../authorization'; diff --git a/x-pack/plugins/cases/server/client/attachments/bulk_create.ts b/x-pack/plugins/cases/server/client/attachments/bulk_create.ts index efd6fa833c9e4..60e98c54631ea 100644 --- a/x-pack/plugins/cases/server/client/attachments/bulk_create.ts +++ b/x-pack/plugins/cases/server/client/attachments/bulk_create.ts @@ -12,20 +12,16 @@ import { identity } from 'fp-ts/lib/function'; import { SavedObjectsUtils } from '@kbn/core/server'; -import { - BulkCreateCommentRequest, - BulkCreateCommentRequestRt, - CaseResponse, - CommentRequest, - throwErrors, -} from '../../../common/api'; +import type { BulkCreateCommentRequest, CaseResponse, CommentRequest } from '../../../common/api'; +import { BulkCreateCommentRequestRt, throwErrors } from '../../../common/api'; import { CaseCommentModel } from '../../common/models'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { decodeCommentRequest } from '../utils'; -import { Operations, OwnerEntity } from '../../authorization'; +import type { OwnerEntity } from '../../authorization'; +import { Operations } from '../../authorization'; export interface BulkCreateArgs { caseId: string; diff --git a/x-pack/plugins/cases/server/client/attachments/client.ts b/x-pack/plugins/cases/server/client/attachments/client.ts index 63b039890aff9..c8cb26a886acf 100644 --- a/x-pack/plugins/cases/server/client/attachments/client.ts +++ b/x-pack/plugins/cases/server/client/attachments/client.ts @@ -5,26 +5,22 @@ * 2.0. */ -import { AlertResponse, CommentResponse } from '../../../common/api'; -import { CasesClient } from '../client'; +import type { AlertResponse, CommentResponse } from '../../../common/api'; +import type { CasesClient } from '../client'; -import { CasesClientInternal } from '../client_internal'; -import { IAllCommentsResponse, ICaseResponse, ICommentsResponse } from '../typedoc_interfaces'; -import { CasesClientArgs } from '../types'; -import { AddArgs, addComment } from './add'; -import { bulkCreate, BulkCreateArgs } from './bulk_create'; -import { DeleteAllArgs, deleteAll, DeleteArgs, deleteComment } from './delete'; -import { - find, - FindArgs, - get, - getAll, - getAllAlertsAttachToCase, - GetAllAlertsAttachToCase, - GetAllArgs, - GetArgs, -} from './get'; -import { update, UpdateArgs } from './update'; +import type { CasesClientInternal } from '../client_internal'; +import type { IAllCommentsResponse, ICaseResponse, ICommentsResponse } from '../typedoc_interfaces'; +import type { CasesClientArgs } from '../types'; +import type { AddArgs } from './add'; +import { addComment } from './add'; +import type { BulkCreateArgs } from './bulk_create'; +import { bulkCreate } from './bulk_create'; +import type { DeleteAllArgs, DeleteArgs } from './delete'; +import { deleteAll, deleteComment } from './delete'; +import type { FindArgs, GetAllAlertsAttachToCase, GetAllArgs, GetArgs } from './get'; +import { find, get, getAll, getAllAlertsAttachToCase } from './get'; +import type { UpdateArgs } from './update'; +import { update } from './update'; /** * API for interacting with the attachments to a case. diff --git a/x-pack/plugins/cases/server/client/attachments/delete.ts b/x-pack/plugins/cases/server/client/attachments/delete.ts index e8ac07d78527f..3a1ad6a358b69 100644 --- a/x-pack/plugins/cases/server/client/attachments/delete.ts +++ b/x-pack/plugins/cases/server/client/attachments/delete.ts @@ -8,10 +8,11 @@ import Boom from '@hapi/boom'; import pMap from 'p-map'; -import { SavedObject } from '@kbn/core/server'; -import { Actions, ActionTypes, CommentAttributes } from '../../../common/api'; +import type { SavedObject } from '@kbn/core/server'; +import type { CommentAttributes } from '../../../common/api'; +import { Actions, ActionTypes } from '../../../common/api'; import { CASE_SAVED_OBJECT, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { createCaseError } from '../../common/error'; import { Operations } from '../../authorization'; diff --git a/x-pack/plugins/cases/server/client/attachments/get.ts b/x-pack/plugins/cases/server/client/attachments/get.ts index 997d0609570b0..adbdd3abf2448 100644 --- a/x-pack/plugins/cases/server/client/attachments/get.ts +++ b/x-pack/plugins/cases/server/client/attachments/get.ts @@ -4,19 +4,17 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { SavedObject } from '@kbn/core/server'; +import type { SavedObject } from '@kbn/core/server'; -import { +import type { AlertResponse, AllCommentsResponse, - AllCommentsResponseRt, AttributesTypeAlerts, CommentResponse, - CommentResponseRt, CommentsResponse, - CommentsResponseRt, FindQueryParams, } from '../../../common/api'; +import { AllCommentsResponseRt, CommentResponseRt, CommentsResponseRt } from '../../../common/api'; import { defaultSortField, transformComments, @@ -26,11 +24,11 @@ import { } from '../../common/utils'; import { createCaseError } from '../../common/error'; import { DEFAULT_PAGE, DEFAULT_PER_PAGE } from '../../routes/api'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { combineFilters, stringToKueryNode } from '../utils'; import { Operations } from '../../authorization'; import { includeFieldsRequiredForAuthentication } from '../../authorization/utils'; -import { CasesClient } from '../client'; +import type { CasesClient } from '../client'; /** * Parameters for finding attachments of a case diff --git a/x-pack/plugins/cases/server/client/attachments/update.ts b/x-pack/plugins/cases/server/client/attachments/update.ts index 674e453c851dd..f1ce5568c78bb 100644 --- a/x-pack/plugins/cases/server/client/attachments/update.ts +++ b/x-pack/plugins/cases/server/client/attachments/update.ts @@ -10,9 +10,9 @@ import Boom from '@hapi/boom'; import { CaseCommentModel } from '../../common/models'; import { createCaseError } from '../../common/error'; import { isCommentRequestTypeExternalReference } from '../../../common/utils/attachments'; -import { CaseResponse, CommentPatchRequest } from '../../../common/api'; +import type { CaseResponse, CommentPatchRequest } from '../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../common/constants'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { decodeCommentRequest } from '../utils'; import { Operations } from '../../authorization'; diff --git a/x-pack/plugins/cases/server/client/cases/client.ts b/x-pack/plugins/cases/server/client/cases/client.ts index b2673eef33dd5..f39f4ab50c5c3 100644 --- a/x-pack/plugins/cases/server/client/cases/client.ts +++ b/x-pack/plugins/cases/server/client/cases/client.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { CasePostRequest, CasesPatchRequest, CasesFindRequest, @@ -14,9 +14,9 @@ import { AllReportersFindRequest, CasesByAlertId, } from '../../../common/api'; -import { CasesClient } from '../client'; -import { CasesClientInternal } from '../client_internal'; -import { +import type { CasesClient } from '../client'; +import type { CasesClientInternal } from '../client_internal'; +import type { ICasePostRequest, ICaseResolveResponse, ICaseResponse, @@ -25,20 +25,14 @@ import { ICasesPatchRequest, ICasesResponse, } from '../typedoc_interfaces'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { create } from './create'; import { deleteCases } from './delete'; import { find } from './find'; -import { - CasesByAlertIDParams, - get, - resolve, - getCasesByAlertID, - GetParams, - getReporters, - getTags, -} from './get'; -import { push, PushParams } from './push'; +import type { CasesByAlertIDParams, GetParams } from './get'; +import { get, resolve, getCasesByAlertID, getReporters, getTags } from './get'; +import type { PushParams } from './push'; +import { push } from './push'; import { update } from './update'; /** diff --git a/x-pack/plugins/cases/server/client/cases/create.ts b/x-pack/plugins/cases/server/client/cases/create.ts index 1a2fa2f9334d8..ba3da0eefe053 100644 --- a/x-pack/plugins/cases/server/client/cases/create.ts +++ b/x-pack/plugins/cases/server/client/cases/create.ts @@ -12,11 +12,10 @@ import { identity } from 'fp-ts/lib/function'; import { SavedObjectsUtils } from '@kbn/core/server'; +import type { CaseResponse, CasePostRequest } from '../../../common/api'; import { throwErrors, CaseResponseRt, - CaseResponse, - CasePostRequest, ActionTypes, CasePostRequestRt, excess, @@ -28,7 +27,7 @@ import { isInvalidTag, areTotalAssigneesInvalid } from '../../../common/utils/va import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; import { flattenCaseSavedObject, transformNewCase } from '../../common/utils'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { LICENSING_CASE_ASSIGNMENT_FEATURE } from '../../common/constants'; /** diff --git a/x-pack/plugins/cases/server/client/cases/delete.ts b/x-pack/plugins/cases/server/client/cases/delete.ts index 95a0c81c00563..7f09bb46288c2 100644 --- a/x-pack/plugins/cases/server/client/cases/delete.ts +++ b/x-pack/plugins/cases/server/client/cases/delete.ts @@ -7,12 +7,13 @@ import pMap from 'p-map'; import { Boom } from '@hapi/boom'; -import { SavedObjectsFindResponse } from '@kbn/core/server'; -import { CommentAttributes } from '../../../common/api'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { CommentAttributes } from '../../../common/api'; import { MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { createCaseError } from '../../common/error'; -import { Operations, OwnerEntity } from '../../authorization'; +import type { OwnerEntity } from '../../authorization'; +import { Operations } from '../../authorization'; /** * Deletes the specified cases and their attachments. diff --git a/x-pack/plugins/cases/server/client/cases/find.ts b/x-pack/plugins/cases/server/client/cases/find.ts index 012c82aac9018..db980c058fbb5 100644 --- a/x-pack/plugins/cases/server/client/cases/find.ts +++ b/x-pack/plugins/cases/server/client/cases/find.ts @@ -11,22 +11,16 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { - CasesFindResponse, - CasesFindRequest, - CasesFindRequestRt, - throwErrors, - CasesFindResponseRt, - excess, -} from '../../../common/api'; +import type { CasesFindResponse, CasesFindRequest } from '../../../common/api'; +import { CasesFindRequestRt, throwErrors, CasesFindResponseRt, excess } from '../../../common/api'; import { createCaseError } from '../../common/error'; import { asArray, transformCases } from '../../common/utils'; import { constructQueryOptions } from '../utils'; import { includeFieldsRequiredForAuthentication } from '../../authorization/utils'; import { Operations } from '../../authorization'; -import { CasesClientArgs } from '..'; -import { ConstructQueryParams } from '../types'; +import type { CasesClientArgs } from '..'; +import type { ConstructQueryParams } from '../types'; import { LICENSING_CASE_ASSIGNMENT_FEATURE } from '../../common/constants'; /** diff --git a/x-pack/plugins/cases/server/client/cases/get.ts b/x-pack/plugins/cases/server/client/cases/get.ts index 210c615d7dd4f..27d098702f4c8 100644 --- a/x-pack/plugins/cases/server/client/cases/get.ts +++ b/x-pack/plugins/cases/server/client/cases/get.ts @@ -9,28 +9,30 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { SavedObject, SavedObjectsResolveResponse } from '@kbn/core/server'; -import { - CaseResponseRt, +import type { SavedObject, SavedObjectsResolveResponse } from '@kbn/core/server'; +import type { CaseResponse, - CaseResolveResponseRt, CaseResolveResponse, User, AllTagsFindRequest, + AllReportersFindRequest, + CasesByAlertIDRequest, + CasesByAlertId, + CaseAttributes, +} from '../../../common/api'; +import { + CaseResponseRt, + CaseResolveResponseRt, AllTagsFindRequestRt, excess, throwErrors, AllReportersFindRequestRt, - AllReportersFindRequest, - CasesByAlertIDRequest, CasesByAlertIDRequestRt, - CasesByAlertId, CasesByAlertIdRt, - CaseAttributes, } from '../../../common/api'; import { createCaseError } from '../../common/error'; import { countAlertsForID, flattenCaseSavedObject } from '../../common/utils'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { Operations } from '../../authorization'; import { combineAuthorizedAndOwnerFilter } from '../utils'; import { CasesService } from '../../services'; diff --git a/x-pack/plugins/cases/server/client/cases/mock.ts b/x-pack/plugins/cases/server/client/cases/mock.ts index a7ffe2a3c8bd3..3d10e459eae8a 100644 --- a/x-pack/plugins/cases/server/client/cases/mock.ts +++ b/x-pack/plugins/cases/server/client/cases/mock.ts @@ -5,14 +5,16 @@ * 2.0. */ -import { +import type { CommentResponse, - CommentType, CaseUserActionsResponse, CommentResponseAlertsType, + ConnectorMappingsAttributes, +} from '../../../common/api'; +import { + CommentType, ConnectorTypes, Actions, - ConnectorMappingsAttributes, ExternalReferenceStorageType, } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; diff --git a/x-pack/plugins/cases/server/client/cases/push.ts b/x-pack/plugins/cases/server/client/cases/push.ts index 6cca689057680..4bc01a8ea62d4 100644 --- a/x-pack/plugins/cases/server/client/cases/push.ts +++ b/x-pack/plugins/cases/server/client/cases/push.ts @@ -7,22 +7,24 @@ import Boom from '@hapi/boom'; import { nodeBuilder } from '@kbn/es-query'; -import { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; -import { UserProfile } from '@kbn/security-plugin/common'; -import { SecurityPluginStart } from '@kbn/security-plugin/server'; -import { +import type { UserProfile } from '@kbn/security-plugin/common'; +import type { SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { ActionConnector, - CaseResponseRt, CaseResponse, - CaseStatuses, ExternalServiceResponse, CasesConfigureAttributes, + CommentRequestAlertType, + CommentAttributes, +} from '../../../common/api'; +import { + CaseResponseRt, + CaseStatuses, ActionTypes, OWNER_FIELD, CommentType, - CommentRequestAlertType, - CommentAttributes, } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT } from '../../../common/constants'; @@ -33,12 +35,12 @@ import { flattenCaseSavedObject, getAlertInfoFromComments, } from '../../common/utils'; -import { CasesClient, CasesClientArgs, CasesClientInternal } from '..'; +import type { CasesClient, CasesClientArgs, CasesClientInternal } from '..'; import { Operations } from '../../authorization'; import { casesConnectors } from '../../connectors'; import { getAlerts } from '../alerts/get'; import { buildFilter } from '../utils'; -import { ICaseResponse } from '../typedoc_interfaces'; +import type { ICaseResponse } from '../typedoc_interfaces'; /** * Returns true if the case should be closed based on the configuration settings. diff --git a/x-pack/plugins/cases/server/client/cases/update.ts b/x-pack/plugins/cases/server/client/cases/update.ts index 70d548851f6e9..1a6f8301ec93f 100644 --- a/x-pack/plugins/cases/server/client/cases/update.ts +++ b/x-pack/plugins/cases/server/client/cases/update.ts @@ -10,24 +10,30 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { SavedObject, SavedObjectsFindResponse, SavedObjectsFindResult } from '@kbn/core/server'; +import type { + SavedObject, + SavedObjectsFindResponse, + SavedObjectsFindResult, +} from '@kbn/core/server'; import { nodeBuilder } from '@kbn/es-query'; import { areTotalAssigneesInvalid } from '../../../common/utils/validators'; -import { +import type { CasePatchRequest, CasesPatchRequest, - CasesPatchRequestRt, CasesResponse, + CommentAttributes, + CaseAttributes, + User, +} from '../../../common/api'; +import { + CasesPatchRequestRt, CasesResponseRt, CaseStatuses, - CommentAttributes, CommentType, excess, throwErrors, - CaseAttributes, - User, } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT, @@ -38,19 +44,20 @@ import { import { getCaseToUpdate } from '../utils'; -import { AlertService, CasesService } from '../../services'; +import type { AlertService, CasesService } from '../../services'; import { createCaseError } from '../../common/error'; import { createAlertUpdateRequest, flattenCaseSavedObject, isCommentRequestTypeAlert, } from '../../common/utils'; -import { UpdateAlertRequest } from '../alerts/types'; -import { CasesClientArgs } from '..'; -import { Operations, OwnerEntity } from '../../authorization'; +import type { UpdateAlertRequest } from '../alerts/types'; +import type { CasesClientArgs } from '..'; +import type { OwnerEntity } from '../../authorization'; +import { Operations } from '../../authorization'; import { dedupAssignees, getClosedInfoForUpdate, getDurationForUpdate } from './utils'; import { LICENSING_CASE_ASSIGNMENT_FEATURE } from '../../common/constants'; -import { LicensingService } from '../../services/licensing'; +import type { LicensingService } from '../../services/licensing'; /** * Throws an error if any of the requests attempt to update the owner of a case. diff --git a/x-pack/plugins/cases/server/client/cases/utils.ts b/x-pack/plugins/cases/server/client/cases/utils.ts index 92bba3fa7e9e1..e56ee316f653a 100644 --- a/x-pack/plugins/cases/server/client/cases/utils.ts +++ b/x-pack/plugins/cases/server/client/cases/utils.ts @@ -6,19 +6,16 @@ */ import { uniqBy, isEmpty } from 'lodash'; -import { UserProfile } from '@kbn/security-plugin/common'; -import { IBasePath } from '@kbn/core-http-browser'; +import type { UserProfile } from '@kbn/security-plugin/common'; +import type { IBasePath } from '@kbn/core-http-browser'; import { CASE_VIEW_PAGE_TABS } from '../../../common/types'; import { isPushedUserAction } from '../../../common/utils/user_actions'; -import { +import type { ActionConnector, CaseFullExternalService, CaseResponse, CaseUserActionsResponse, CommentResponse, - CommentType, - ActionTypes, - CaseStatuses, User, CaseAttributes, CaseAssignees, @@ -26,10 +23,11 @@ import { CaseField, ThirdPartyField, } from '../../../common/api'; -import { CasesClientGetAlertsResponse } from '../alerts/types'; -import { ExternalServiceComment, ExternalServiceIncident } from './types'; +import { CommentType, ActionTypes, CaseStatuses } from '../../../common/api'; +import type { CasesClientGetAlertsResponse } from '../alerts/types'; +import type { ExternalServiceComment, ExternalServiceIncident } from './types'; import { getAlertIds } from '../utils'; -import { CasesConnectorsMap } from '../../connectors'; +import type { CasesConnectorsMap } from '../../connectors'; import { getCaseViewPath } from '../../common/utils'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/server/client/client.ts b/x-pack/plugins/cases/server/client/client.ts index 266c988212cdf..c37a96db89a1b 100644 --- a/x-pack/plugins/cases/server/client/client.ts +++ b/x-pack/plugins/cases/server/client/client.ts @@ -5,13 +5,19 @@ * 2.0. */ -import { CasesClientArgs } from './types'; -import { CasesSubClient, createCasesSubClient } from './cases/client'; -import { AttachmentsSubClient, createAttachmentsSubClient } from './attachments/client'; -import { UserActionsSubClient, createUserActionsSubClient } from './user_actions/client'; -import { CasesClientInternal, createCasesClientInternal } from './client_internal'; -import { ConfigureSubClient, createConfigurationSubClient } from './configure/client'; -import { createMetricsSubClient, MetricsSubClient } from './metrics/client'; +import type { CasesClientArgs } from './types'; +import type { CasesSubClient } from './cases/client'; +import { createCasesSubClient } from './cases/client'; +import type { AttachmentsSubClient } from './attachments/client'; +import { createAttachmentsSubClient } from './attachments/client'; +import type { UserActionsSubClient } from './user_actions/client'; +import { createUserActionsSubClient } from './user_actions/client'; +import type { CasesClientInternal } from './client_internal'; +import { createCasesClientInternal } from './client_internal'; +import type { ConfigureSubClient } from './configure/client'; +import { createConfigurationSubClient } from './configure/client'; +import type { MetricsSubClient } from './metrics/client'; +import { createMetricsSubClient } from './metrics/client'; /** * Client wrapper that contains accessor methods for individual entities within the cases system. diff --git a/x-pack/plugins/cases/server/client/client_internal.ts b/x-pack/plugins/cases/server/client/client_internal.ts index 57b9a0ffbc243..c7489cdeb133a 100644 --- a/x-pack/plugins/cases/server/client/client_internal.ts +++ b/x-pack/plugins/cases/server/client/client_internal.ts @@ -5,11 +5,9 @@ * 2.0. */ -import { CasesClientArgs } from './types'; -import { - InternalConfigureSubClient, - createInternalConfigurationSubClient, -} from './configure/client'; +import type { CasesClientArgs } from './types'; +import type { InternalConfigureSubClient } from './configure/client'; +import { createInternalConfigurationSubClient } from './configure/client'; export class CasesClientInternal { private readonly _configuration: InternalConfigureSubClient; diff --git a/x-pack/plugins/cases/server/client/configure/client.test.ts b/x-pack/plugins/cases/server/client/configure/client.test.ts index 126e479238a25..7ee4bddf1d5a5 100644 --- a/x-pack/plugins/cases/server/client/configure/client.test.ts +++ b/x-pack/plugins/cases/server/client/configure/client.test.ts @@ -7,7 +7,7 @@ import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsClientMock } from '@kbn/actions-plugin/server/mocks'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { getConnectors } from './client'; describe('client', () => { diff --git a/x-pack/plugins/cases/server/client/configure/client.ts b/x-pack/plugins/cases/server/client/configure/client.ts index 8efc9d82ea322..aae777d66ea2f 100644 --- a/x-pack/plugins/cases/server/client/configure/client.ts +++ b/x-pack/plugins/cases/server/client/configure/client.ts @@ -11,37 +11,41 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { SavedObject, SavedObjectsFindResponse, SavedObjectsUtils } from '@kbn/core/server'; -import { FindActionResult } from '@kbn/actions-plugin/server/types'; -import { ActionType, CasesConnectorFeatureId } from '@kbn/actions-plugin/common'; -import { - CaseConfigurationsResponseRt, - CaseConfigureResponseRt, +import type { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server'; +import { SavedObjectsUtils } from '@kbn/core/server'; +import type { FindActionResult } from '@kbn/actions-plugin/server/types'; +import type { ActionType } from '@kbn/actions-plugin/common'; +import { CasesConnectorFeatureId } from '@kbn/actions-plugin/common'; +import type { CasesConfigurationsResponse, CasesConfigureAttributes, CasesConfigurePatch, - CasesConfigurePatchRt, CasesConfigureRequest, CasesConfigureResponse, ConnectorMappings, ConnectorMappingsAttributes, - excess, GetConfigureFindRequest, +} from '../../../common/api'; +import { + CaseConfigurationsResponseRt, + CaseConfigureResponseRt, + CasesConfigurePatchRt, + excess, GetConfigureFindRequestRt, throwErrors, } from '../../../common/api'; import { MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; import { createCaseError } from '../../common/error'; -import { CasesClientInternal } from '../client_internal'; -import { CasesClientArgs } from '../types'; +import type { CasesClientInternal } from '../client_internal'; +import type { CasesClientArgs } from '../types'; import { getMappings } from './get_mappings'; import { Operations } from '../../authorization'; import { combineAuthorizedAndOwnerFilter } from '../utils'; -import { MappingsArgs, CreateMappingsArgs, UpdateMappingsArgs } from './types'; +import type { MappingsArgs, CreateMappingsArgs, UpdateMappingsArgs } from './types'; import { createMappings } from './create_mappings'; import { updateMappings } from './update_mappings'; -import { +import type { ICasesConfigurePatch, ICasesConfigureRequest, ICasesConfigureResponse, diff --git a/x-pack/plugins/cases/server/client/configure/create_mappings.ts b/x-pack/plugins/cases/server/client/configure/create_mappings.ts index f69f740ae2fcb..904c7accede14 100644 --- a/x-pack/plugins/cases/server/client/configure/create_mappings.ts +++ b/x-pack/plugins/cases/server/client/configure/create_mappings.ts @@ -6,10 +6,10 @@ */ import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { ConnectorMappingsAttributes } from '../../../common/api'; +import type { ConnectorMappingsAttributes } from '../../../common/api'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; -import { CreateMappingsArgs } from './types'; +import type { CasesClientArgs } from '..'; +import type { CreateMappingsArgs } from './types'; import { casesConnectors } from '../../connectors'; export const createMappings = async ( diff --git a/x-pack/plugins/cases/server/client/configure/get_mappings.ts b/x-pack/plugins/cases/server/client/configure/get_mappings.ts index 464619e800368..845425d8044d4 100644 --- a/x-pack/plugins/cases/server/client/configure/get_mappings.ts +++ b/x-pack/plugins/cases/server/client/configure/get_mappings.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { ConnectorMappings } from '../../../common/api'; +import type { ConnectorMappings } from '../../../common/api'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; -import { MappingsArgs } from './types'; +import type { CasesClientArgs } from '..'; +import type { MappingsArgs } from './types'; export const getMappings = async ( { connector }: MappingsArgs, diff --git a/x-pack/plugins/cases/server/client/configure/types.ts b/x-pack/plugins/cases/server/client/configure/types.ts index d425b7f67d908..4885ae0720ead 100644 --- a/x-pack/plugins/cases/server/client/configure/types.ts +++ b/x-pack/plugins/cases/server/client/configure/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { CaseConnector } from '../../../common/api'; -import { IndexRefresh } from '../../services/types'; +import type { CaseConnector } from '../../../common/api'; +import type { IndexRefresh } from '../../services/types'; export interface MappingsArgs { connector: CaseConnector; diff --git a/x-pack/plugins/cases/server/client/configure/update_mappings.ts b/x-pack/plugins/cases/server/client/configure/update_mappings.ts index ea1bcb69809c7..12da43213b05a 100644 --- a/x-pack/plugins/cases/server/client/configure/update_mappings.ts +++ b/x-pack/plugins/cases/server/client/configure/update_mappings.ts @@ -6,10 +6,10 @@ */ import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { ConnectorMappingsAttributes } from '../../../common/api'; +import type { ConnectorMappingsAttributes } from '../../../common/api'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; -import { UpdateMappingsArgs } from './types'; +import type { CasesClientArgs } from '..'; +import type { UpdateMappingsArgs } from './types'; import { casesConnectors } from '../../connectors'; export const updateMappings = async ( diff --git a/x-pack/plugins/cases/server/client/factory.ts b/x-pack/plugins/cases/server/client/factory.ts index 960c55e2882e3..f3376686f9ad5 100644 --- a/x-pack/plugins/cases/server/client/factory.ts +++ b/x-pack/plugins/cases/server/client/factory.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { KibanaRequest, SavedObjectsServiceStart, Logger, @@ -13,12 +13,12 @@ import { SavedObjectsClientContract, IBasePath, } from '@kbn/core/server'; -import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; -import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; -import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; -import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; -import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; -import { LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { SAVED_OBJECT_TYPES } from '../../common/constants'; import { Authorization } from '../authorization/authorization'; import { @@ -31,10 +31,11 @@ import { } from '../services'; import { AuthorizationAuditLogger } from '../authorization'; -import { CasesClient, createCasesClient } from '.'; -import { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; -import { ExternalReferenceAttachmentTypeRegistry } from '../attachment_framework/external_reference_registry'; -import { CasesServices } from './types'; +import type { CasesClient } from '.'; +import { createCasesClient } from '.'; +import type { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; +import type { ExternalReferenceAttachmentTypeRegistry } from '../attachment_framework/external_reference_registry'; +import type { CasesServices } from './types'; import { LicensingService } from '../services/licensing'; interface CasesClientFactoryArgs { diff --git a/x-pack/plugins/cases/server/client/metrics/actions/actions.test.ts b/x-pack/plugins/cases/server/client/metrics/actions/actions.test.ts index f461dec56b346..e8211662c1820 100644 --- a/x-pack/plugins/cases/server/client/metrics/actions/actions.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/actions/actions.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CaseResponse } from '../../../../common/api'; +import type { CaseResponse } from '../../../../common/api'; import { createCasesClientMock } from '../../mocks'; -import { CasesClientArgs } from '../../types'; +import type { CasesClientArgs } from '../../types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { createAttachmentServiceMock } from '../../../services/mocks'; diff --git a/x-pack/plugins/cases/server/client/metrics/actions/actions.ts b/x-pack/plugins/cases/server/client/metrics/actions/actions.ts index fbb060687a79f..ce2f71553f274 100644 --- a/x-pack/plugins/cases/server/client/metrics/actions/actions.ts +++ b/x-pack/plugins/cases/server/client/metrics/actions/actions.ts @@ -6,11 +6,11 @@ */ import { merge } from 'lodash'; -import { SingleCaseMetricsResponse } from '../../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../../common/api'; import { Operations } from '../../../authorization'; import { createCaseError } from '../../../common/error'; import { SingleCaseAggregationHandler } from '../single_case_aggregation_handler'; -import { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from '../types'; +import type { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from '../types'; import { IsolateHostActions } from './aggregations/isolate_host'; export class Actions extends SingleCaseAggregationHandler { diff --git a/x-pack/plugins/cases/server/client/metrics/actions/aggregations/isolate_host.ts b/x-pack/plugins/cases/server/client/metrics/actions/aggregations/isolate_host.ts index 479de16bc262f..b6aa821bee875 100644 --- a/x-pack/plugins/cases/server/client/metrics/actions/aggregations/isolate_host.ts +++ b/x-pack/plugins/cases/server/client/metrics/actions/aggregations/isolate_host.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { IsolateHostActionType, SingleCaseMetricsResponse } from '../../../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../../../common/api'; +import { IsolateHostActionType } from '../../../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT } from '../../../../../common/constants'; -import { AggregationBuilder, AggregationResponse } from '../../types'; +import type { AggregationBuilder, AggregationResponse } from '../../types'; interface ActionsAggregation { actions?: { diff --git a/x-pack/plugins/cases/server/client/metrics/aggregation_handler.ts b/x-pack/plugins/cases/server/client/metrics/aggregation_handler.ts index e70c7add20f5e..d3ea78d7ccf2f 100644 --- a/x-pack/plugins/cases/server/client/metrics/aggregation_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/aggregation_handler.ts @@ -7,7 +7,7 @@ import { merge } from 'lodash'; import { BaseHandler } from './base_handler'; -import { AggregationBuilder, AggregationResponse, BaseHandlerCommonOptions } from './types'; +import type { AggregationBuilder, AggregationResponse, BaseHandlerCommonOptions } from './types'; export abstract class AggregationHandler extends BaseHandler { protected aggregationBuilders: Array> = []; diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/hosts.ts b/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/hosts.ts index a9052e2e2a9ce..31ebb33084ab7 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/hosts.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/hosts.ts @@ -8,8 +8,8 @@ import { get } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { SingleCaseMetricsResponse } from '../../../../../common/api'; -import { AggregationBuilder, AggregationResponse } from '../../types'; +import type { SingleCaseMetricsResponse } from '../../../../../common/api'; +import type { AggregationBuilder, AggregationResponse } from '../../types'; type HostsAggregate = HostsAggregateResponse | undefined; diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/users.ts b/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/users.ts index 8d068e354693b..68eedcc6d3f94 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/users.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/aggregations/users.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../../../common/api'; -import { AggregationBuilder, AggregationResponse } from '../../types'; +import type { SingleCaseMetricsResponse } from '../../../../../common/api'; +import type { AggregationBuilder, AggregationResponse } from '../../types'; export class AlertUsers implements AggregationBuilder { constructor(private readonly uniqueValuesLimit: number = 10) {} diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/count.test.ts b/x-pack/plugins/cases/server/client/metrics/alerts/count.test.ts index 9f0a5860beefb..15209b1608194 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/count.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/count.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CaseResponse } from '../../../../common/api'; +import type { CaseResponse } from '../../../../common/api'; import { createCasesClientMock } from '../../mocks'; -import { CasesClientArgs } from '../../types'; +import type { CasesClientArgs } from '../../types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { createAttachmentServiceMock } from '../../../services/mocks'; diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/count.ts b/x-pack/plugins/cases/server/client/metrics/alerts/count.ts index 9ae64f457436d..f5f7e0d2be560 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/count.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/count.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../../common/api'; import { Operations } from '../../../authorization'; import { createCaseError } from '../../../common/error'; import { SingleCaseBaseHandler } from '../single_case_base_handler'; -import { SingleCaseBaseHandlerCommonOptions } from '../types'; +import type { SingleCaseBaseHandlerCommonOptions } from '../types'; export class AlertsCount extends SingleCaseBaseHandler { constructor(options: SingleCaseBaseHandlerCommonOptions) { diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/details.test.ts b/x-pack/plugins/cases/server/client/metrics/alerts/details.test.ts index 7b0a68802c4a1..23797b75992e4 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/details.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/details.test.ts @@ -5,13 +5,14 @@ * 2.0. */ -import { CasesClientMock, createCasesClientMock } from '../../mocks'; -import { CasesClientArgs } from '../../types'; +import type { CasesClientMock } from '../../mocks'; +import { createCasesClientMock } from '../../mocks'; +import type { CasesClientArgs } from '../../types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { AlertDetails } from './details'; import { mockAlertsService } from '../test_utils/alerts'; -import { SingleCaseBaseHandlerCommonOptions } from '../types'; +import type { SingleCaseBaseHandlerCommonOptions } from '../types'; describe('AlertDetails', () => { let client: CasesClientMock; diff --git a/x-pack/plugins/cases/server/client/metrics/alerts/details.ts b/x-pack/plugins/cases/server/client/metrics/alerts/details.ts index b361df48bebc0..75e96482ae9c0 100644 --- a/x-pack/plugins/cases/server/client/metrics/alerts/details.ts +++ b/x-pack/plugins/cases/server/client/metrics/alerts/details.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../../common/api'; import { createCaseError } from '../../../common/error'; import { SingleCaseAggregationHandler } from '../single_case_aggregation_handler'; -import { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from '../types'; +import type { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from '../types'; import { AlertHosts, AlertUsers } from './aggregations'; export class AlertDetails extends SingleCaseAggregationHandler { diff --git a/x-pack/plugins/cases/server/client/metrics/all_cases/aggregations/avg_duration.ts b/x-pack/plugins/cases/server/client/metrics/all_cases/aggregations/avg_duration.ts index 03d0595f7ec7a..1239cfaf9a943 100644 --- a/x-pack/plugins/cases/server/client/metrics/all_cases/aggregations/avg_duration.ts +++ b/x-pack/plugins/cases/server/client/metrics/all_cases/aggregations/avg_duration.ts @@ -6,8 +6,8 @@ */ import { CASE_SAVED_OBJECT } from '../../../../../common/constants'; -import { CasesMetricsResponse } from '../../../../../common/api'; -import { AggregationBuilder, AggregationResponse } from '../../types'; +import type { CasesMetricsResponse } from '../../../../../common/api'; +import type { AggregationBuilder, AggregationResponse } from '../../types'; export class AverageDuration implements AggregationBuilder { build() { diff --git a/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.test.ts b/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.test.ts index be640569c56b1..a13346d2ecfab 100644 --- a/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CaseResponse } from '../../../../common/api'; +import type { CaseResponse } from '../../../../common/api'; import { createCasesClientMock } from '../../mocks'; -import { CasesClientArgs } from '../../types'; +import type { CasesClientArgs } from '../../types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { createCaseServiceMock } from '../../../services/mocks'; diff --git a/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.ts b/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.ts index 79ae801e8a19e..51e9d0ccfaa0f 100644 --- a/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.ts +++ b/x-pack/plugins/cases/server/client/metrics/all_cases/mttr.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { CasesMetricsResponse } from '../../../../common/api'; +import type { CasesMetricsResponse } from '../../../../common/api'; import { Operations } from '../../../authorization'; import { createCaseError } from '../../../common/error'; import { constructQueryOptions } from '../../utils'; import { AllCasesAggregationHandler } from '../all_cases_aggregation_handler'; -import { AggregationBuilder, AllCasesBaseHandlerCommonOptions } from '../types'; +import type { AggregationBuilder, AllCasesBaseHandlerCommonOptions } from '../types'; import { AverageDuration } from './aggregations/avg_duration'; export class MTTR extends AllCasesAggregationHandler { diff --git a/x-pack/plugins/cases/server/client/metrics/all_cases_aggregation_handler.ts b/x-pack/plugins/cases/server/client/metrics/all_cases_aggregation_handler.ts index 3a5a259c28296..57f9442e8d63d 100644 --- a/x-pack/plugins/cases/server/client/metrics/all_cases_aggregation_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/all_cases_aggregation_handler.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CasesMetricsResponse } from '../../../common/api'; +import type { CasesMetricsResponse } from '../../../common/api'; import { AggregationHandler } from './aggregation_handler'; -import { AggregationBuilder, AllCasesBaseHandlerCommonOptions } from './types'; +import type { AggregationBuilder, AllCasesBaseHandlerCommonOptions } from './types'; export abstract class AllCasesAggregationHandler extends AggregationHandler { protected readonly from?: string; diff --git a/x-pack/plugins/cases/server/client/metrics/all_cases_base_handler.ts b/x-pack/plugins/cases/server/client/metrics/all_cases_base_handler.ts index de9f1f089c8c8..d4303d8c41d8c 100644 --- a/x-pack/plugins/cases/server/client/metrics/all_cases_base_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/all_cases_base_handler.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CasesMetricsResponse } from '../../../common/api'; +import type { CasesMetricsResponse } from '../../../common/api'; import { BaseHandler } from './base_handler'; -import { AllCasesBaseHandlerCommonOptions } from './types'; +import type { AllCasesBaseHandlerCommonOptions } from './types'; export abstract class AllCasesBaseHandler extends BaseHandler { protected readonly owner?: string | string[]; diff --git a/x-pack/plugins/cases/server/client/metrics/base_handler.ts b/x-pack/plugins/cases/server/client/metrics/base_handler.ts index 6525de35bc00c..92117fb6f34cf 100644 --- a/x-pack/plugins/cases/server/client/metrics/base_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/base_handler.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { BaseHandlerCommonOptions, MetricsHandler } from './types'; +import type { BaseHandlerCommonOptions, MetricsHandler } from './types'; export abstract class BaseHandler implements MetricsHandler { constructor( diff --git a/x-pack/plugins/cases/server/client/metrics/client.ts b/x-pack/plugins/cases/server/client/metrics/client.ts index e2e0dfb5c9415..bbf85cc2a0184 100644 --- a/x-pack/plugins/cases/server/client/metrics/client.ts +++ b/x-pack/plugins/cases/server/client/metrics/client.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { SingleCaseMetricsResponse, CasesMetricsRequest, CasesStatusRequest, @@ -13,9 +13,9 @@ import { SingleCaseMetricsRequest, CasesMetricsResponse, } from '../../../common/api'; -import { CasesClient } from '../client'; +import type { CasesClient } from '../client'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { getStatusTotalsByType } from './get_status_totals'; import { getCaseMetrics } from './get_case_metrics'; import { getCasesMetrics } from './get_cases_metrics'; diff --git a/x-pack/plugins/cases/server/client/metrics/connectors.test.ts b/x-pack/plugins/cases/server/client/metrics/connectors.test.ts index d8c71aa57d09c..6983eb16b0a31 100644 --- a/x-pack/plugins/cases/server/client/metrics/connectors.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/connectors.test.ts @@ -6,7 +6,7 @@ */ import { createCasesClientMock } from '../mocks'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { createUserActionServiceMock } from '../../services/mocks'; import { Connectors } from './connectors'; diff --git a/x-pack/plugins/cases/server/client/metrics/connectors.ts b/x-pack/plugins/cases/server/client/metrics/connectors.ts index b75225ddf8eb7..e5ab7c2856048 100644 --- a/x-pack/plugins/cases/server/client/metrics/connectors.ts +++ b/x-pack/plugins/cases/server/client/metrics/connectors.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../common/api'; import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; import { SingleCaseBaseHandler } from './single_case_base_handler'; -import { SingleCaseBaseHandlerCommonOptions } from './types'; +import type { SingleCaseBaseHandlerCommonOptions } from './types'; export class Connectors extends SingleCaseBaseHandler { constructor(options: SingleCaseBaseHandlerCommonOptions) { diff --git a/x-pack/plugins/cases/server/client/metrics/get_case_metrics.test.ts b/x-pack/plugins/cases/server/client/metrics/get_case_metrics.test.ts index cf88f3d9fcd68..61c11ad4c7adc 100644 --- a/x-pack/plugins/cases/server/client/metrics/get_case_metrics.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/get_case_metrics.test.ts @@ -6,12 +6,14 @@ */ import { loggingSystemMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { SavedObject } from '@kbn/core/server'; +import type { SavedObject } from '@kbn/core/server'; import { getCaseMetrics } from './get_case_metrics'; -import { CaseAttributes, CaseResponse, CaseStatuses } from '../../../common/api'; -import { CasesClientMock, createCasesClientMock } from '../mocks'; -import { CasesClientArgs } from '../types'; +import type { CaseAttributes, CaseResponse } from '../../../common/api'; +import { CaseStatuses } from '../../../common/api'; +import type { CasesClientMock } from '../mocks'; +import { createCasesClientMock } from '../mocks'; +import type { CasesClientArgs } from '../types'; import { createAuthorizationMock } from '../../authorization/mock'; import { createAttachmentServiceMock, diff --git a/x-pack/plugins/cases/server/client/metrics/get_case_metrics.ts b/x-pack/plugins/cases/server/client/metrics/get_case_metrics.ts index ea54a7556056f..154d90dfc8333 100644 --- a/x-pack/plugins/cases/server/client/metrics/get_case_metrics.ts +++ b/x-pack/plugins/cases/server/client/metrics/get_case_metrics.ts @@ -6,15 +6,12 @@ */ import { merge } from 'lodash'; -import { - SingleCaseMetricsRequest, - SingleCaseMetricsResponse, - SingleCaseMetricsResponseRt, -} from '../../../common/api'; +import type { SingleCaseMetricsRequest, SingleCaseMetricsResponse } from '../../../common/api'; +import { SingleCaseMetricsResponseRt } from '../../../common/api'; import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; -import { CasesClient } from '../client'; -import { CasesClientArgs } from '../types'; +import type { CasesClient } from '../client'; +import type { CasesClientArgs } from '../types'; import { buildHandlers } from './utils'; export const getCaseMetrics = async ( diff --git a/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.test.ts b/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.test.ts index fca356132363f..2e043a8fedf5f 100644 --- a/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesClientMock } from '../mocks'; +import type { CasesClientMock } from '../mocks'; import { getCasesMetrics } from './get_cases_metrics'; import { createMockClientArgs, createMockClient } from './test_utils/client'; diff --git a/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.ts b/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.ts index c7cb0673db42e..49a88bfbdb6e5 100644 --- a/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.ts +++ b/x-pack/plugins/cases/server/client/metrics/get_cases_metrics.ts @@ -11,16 +11,11 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { - CasesMetricsRequest, - CasesMetricsRequestRt, - CasesMetricsResponse, - CasesMetricsResponseRt, - throwErrors, -} from '../../../common/api'; +import type { CasesMetricsRequest, CasesMetricsResponse } from '../../../common/api'; +import { CasesMetricsRequestRt, CasesMetricsResponseRt, throwErrors } from '../../../common/api'; import { createCaseError } from '../../common/error'; -import { CasesClient } from '../client'; -import { CasesClientArgs } from '../types'; +import type { CasesClient } from '../client'; +import type { CasesClientArgs } from '../types'; import { buildHandlers } from './utils'; export const getCasesMetrics = async ( diff --git a/x-pack/plugins/cases/server/client/metrics/get_status_totals.ts b/x-pack/plugins/cases/server/client/metrics/get_status_totals.ts index b0b3c2f91f0d7..c04f31cf9ac94 100644 --- a/x-pack/plugins/cases/server/client/metrics/get_status_totals.ts +++ b/x-pack/plugins/cases/server/client/metrics/get_status_totals.ts @@ -10,15 +10,14 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; +import type { CasesStatusRequest, CasesStatusResponse } from '../../../common/api'; import { - CasesStatusRequest, - CasesStatusResponse, excess, CasesStatusRequestRt, throwErrors, CasesStatusResponseRt, } from '../../../common/api'; -import { CasesClientArgs } from '../types'; +import type { CasesClientArgs } from '../types'; import { Operations } from '../../authorization'; import { constructQueryOptions } from '../utils'; import { createCaseError } from '../../common/error'; diff --git a/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts b/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts index efb9062bfdfe0..c76f25cb15244 100644 --- a/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts +++ b/x-pack/plugins/cases/server/client/metrics/lifespan.test.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { SavedObject } from '@kbn/core/server'; -import { CaseStatuses, CaseUserActionResponse } from '../../../common/api'; +import type { SavedObject } from '@kbn/core/server'; +import type { CaseUserActionResponse } from '../../../common/api'; +import { CaseStatuses } from '../../../common/api'; import { getStatusInfo } from './lifespan'; describe('lifespan', () => { diff --git a/x-pack/plugins/cases/server/client/metrics/lifespan.ts b/x-pack/plugins/cases/server/client/metrics/lifespan.ts index 361ce85caae8f..e040228622b0b 100644 --- a/x-pack/plugins/cases/server/client/metrics/lifespan.ts +++ b/x-pack/plugins/cases/server/client/metrics/lifespan.ts @@ -5,20 +5,19 @@ * 2.0. */ -import { SavedObject } from '@kbn/core/server'; -import { - CaseStatuses, +import type { SavedObject } from '@kbn/core/server'; +import type { CaseUserActionResponse, SingleCaseMetricsResponse, StatusInfo, StatusUserAction, - StatusUserActionRt, UserActionWithResponse, } from '../../../common/api'; +import { CaseStatuses, StatusUserActionRt } from '../../../common/api'; import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; import { SingleCaseBaseHandler } from './single_case_base_handler'; -import { SingleCaseBaseHandlerCommonOptions } from './types'; +import type { SingleCaseBaseHandlerCommonOptions } from './types'; export class Lifespan extends SingleCaseBaseHandler { constructor(options: SingleCaseBaseHandlerCommonOptions) { diff --git a/x-pack/plugins/cases/server/client/metrics/single_case_aggregation_handler.ts b/x-pack/plugins/cases/server/client/metrics/single_case_aggregation_handler.ts index 509a2f0125ec6..ffdf8bbf38396 100644 --- a/x-pack/plugins/cases/server/client/metrics/single_case_aggregation_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/single_case_aggregation_handler.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../common/api'; import { AggregationHandler } from './aggregation_handler'; -import { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from './types'; +import type { AggregationBuilder, SingleCaseBaseHandlerCommonOptions } from './types'; export abstract class SingleCaseAggregationHandler extends AggregationHandler { protected readonly caseId: string; diff --git a/x-pack/plugins/cases/server/client/metrics/single_case_base_handler.ts b/x-pack/plugins/cases/server/client/metrics/single_case_base_handler.ts index d11af800186b0..054263739dd83 100644 --- a/x-pack/plugins/cases/server/client/metrics/single_case_base_handler.ts +++ b/x-pack/plugins/cases/server/client/metrics/single_case_base_handler.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SingleCaseMetricsResponse } from '../../../common/api'; +import type { SingleCaseMetricsResponse } from '../../../common/api'; import { BaseHandler } from './base_handler'; -import { SingleCaseBaseHandlerCommonOptions } from './types'; +import type { SingleCaseBaseHandlerCommonOptions } from './types'; export abstract class SingleCaseBaseHandler extends BaseHandler { protected readonly caseId: string; diff --git a/x-pack/plugins/cases/server/client/metrics/test_utils/alerts.ts b/x-pack/plugins/cases/server/client/metrics/test_utils/alerts.ts index 73d22fb575f27..2a549d08e643e 100644 --- a/x-pack/plugins/cases/server/client/metrics/test_utils/alerts.ts +++ b/x-pack/plugins/cases/server/client/metrics/test_utils/alerts.ts @@ -6,7 +6,7 @@ */ import { createAlertServiceMock } from '../../../services/mocks'; -import { AggregationBuilder } from '../types'; +import type { AggregationBuilder } from '../types'; import { AlertHosts, AlertUsers } from '../alerts/aggregations'; export function mockAlertsService() { diff --git a/x-pack/plugins/cases/server/client/metrics/test_utils/client.ts b/x-pack/plugins/cases/server/client/metrics/test_utils/client.ts index 4bc3eedf18660..df66f92cd872a 100644 --- a/x-pack/plugins/cases/server/client/metrics/test_utils/client.ts +++ b/x-pack/plugins/cases/server/client/metrics/test_utils/client.ts @@ -9,7 +9,7 @@ import { savedObjectsClientMock, loggingSystemMock } from '@kbn/core/server/mock import { createAuthorizationMock } from '../../../authorization/mock'; import { createCaseServiceMock } from '../../../services/mocks'; import { createCasesClientMock } from '../../mocks'; -import { CasesClientArgs } from '../../types'; +import type { CasesClientArgs } from '../../types'; export function createMockClient() { const client = createCasesClientMock(); diff --git a/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts b/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts index 2e5176b6f21a6..a5b200f123eb9 100644 --- a/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts +++ b/x-pack/plugins/cases/server/client/metrics/test_utils/lifespan.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObject } from '@kbn/core/server'; -import { CaseStatuses, CaseUserActionResponse } from '../../../../common/api'; +import type { SavedObject } from '@kbn/core/server'; +import type { CaseStatuses, CaseUserActionResponse } from '../../../../common/api'; export function createStatusChangeSavedObject( status: CaseStatuses, diff --git a/x-pack/plugins/cases/server/client/metrics/types.ts b/x-pack/plugins/cases/server/client/metrics/types.ts index 35bdbc0933fbc..829d736919558 100644 --- a/x-pack/plugins/cases/server/client/metrics/types.ts +++ b/x-pack/plugins/cases/server/client/metrics/types.ts @@ -6,8 +6,8 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { CasesClient } from '../client'; -import { CasesClientArgs } from '../types'; +import type { CasesClient } from '../client'; +import type { CasesClientArgs } from '../types'; export interface MetricsHandler { getFeatures(): Set; diff --git a/x-pack/plugins/cases/server/client/metrics/utils.ts b/x-pack/plugins/cases/server/client/metrics/utils.ts index 9d6634d888d71..90d7b40658456 100644 --- a/x-pack/plugins/cases/server/client/metrics/utils.ts +++ b/x-pack/plugins/cases/server/client/metrics/utils.ts @@ -6,15 +6,15 @@ */ import Boom from '@hapi/boom'; -import { CasesMetricsRequest, SingleCaseMetricsRequest } from '../../../common/api'; -import { CasesClient } from '../client'; -import { CasesClientArgs } from '../types'; +import type { CasesMetricsRequest, SingleCaseMetricsRequest } from '../../../common/api'; +import type { CasesClient } from '../client'; +import type { CasesClientArgs } from '../types'; import { AlertsCount } from './alerts/count'; import { AlertDetails } from './alerts/details'; import { Actions } from './actions'; import { Connectors } from './connectors'; import { Lifespan } from './lifespan'; -import { MetricsHandler } from './types'; +import type { MetricsHandler } from './types'; import { MTTR } from './all_cases/mttr'; const isSingleCaseMetrics = ( diff --git a/x-pack/plugins/cases/server/client/mocks.ts b/x-pack/plugins/cases/server/client/mocks.ts index a5842cf9137ba..cfaf5437f5c7f 100644 --- a/x-pack/plugins/cases/server/client/mocks.ts +++ b/x-pack/plugins/cases/server/client/mocks.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { PublicContract, PublicMethodsOf } from '@kbn/utility-types'; - -import { CasesClient } from '.'; -import { AttachmentsSubClient } from './attachments/client'; -import { CasesSubClient } from './cases/client'; -import { ConfigureSubClient } from './configure/client'; -import { CasesClientFactory } from './factory'; -import { MetricsSubClient } from './metrics/client'; -import { UserActionsSubClient } from './user_actions/client'; +import type { PublicContract, PublicMethodsOf } from '@kbn/utility-types'; + +import type { CasesClient } from '.'; +import type { AttachmentsSubClient } from './attachments/client'; +import type { CasesSubClient } from './cases/client'; +import type { ConfigureSubClient } from './configure/client'; +import type { CasesClientFactory } from './factory'; +import type { MetricsSubClient } from './metrics/client'; +import type { UserActionsSubClient } from './user_actions/client'; type CasesSubClientMock = jest.Mocked; diff --git a/x-pack/plugins/cases/server/client/typedoc_interfaces.ts b/x-pack/plugins/cases/server/client/typedoc_interfaces.ts index 22fb20f54321b..d98f4c08cbeda 100644 --- a/x-pack/plugins/cases/server/client/typedoc_interfaces.ts +++ b/x-pack/plugins/cases/server/client/typedoc_interfaces.ts @@ -13,7 +13,7 @@ /* eslint-disable @typescript-eslint/no-empty-interface */ -import { +import type { AllCommentsResponse, CasePostRequest, CaseResolveResponse, diff --git a/x-pack/plugins/cases/server/client/types.ts b/x-pack/plugins/cases/server/client/types.ts index 81d17420b4c88..1232cd0f9affe 100644 --- a/x-pack/plugins/cases/server/client/types.ts +++ b/x-pack/plugins/cases/server/client/types.ts @@ -6,15 +6,15 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import { ActionsClient } from '@kbn/actions-plugin/server'; -import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; -import { KueryNode } from '@kbn/es-query'; -import { SecurityPluginStart } from '@kbn/security-plugin/server'; -import { IBasePath } from '@kbn/core-http-browser'; -import { CaseSeverity, CaseStatuses, User } from '../../common/api'; -import { Authorization } from '../authorization/authorization'; -import { +import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; +import type { ActionsClient } from '@kbn/actions-plugin/server'; +import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import type { KueryNode } from '@kbn/es-query'; +import type { SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { IBasePath } from '@kbn/core-http-browser'; +import type { CaseSeverity, CaseStatuses, User } from '../../common/api'; +import type { Authorization } from '../authorization/authorization'; +import type { CaseConfigureService, CasesService, CaseUserActionService, @@ -22,9 +22,9 @@ import { AttachmentService, AlertService, } from '../services'; -import { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; -import { ExternalReferenceAttachmentTypeRegistry } from '../attachment_framework/external_reference_registry'; -import { LicensingService } from '../services/licensing'; +import type { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; +import type { ExternalReferenceAttachmentTypeRegistry } from '../attachment_framework/external_reference_registry'; +import type { LicensingService } from '../services/licensing'; export interface CasesServices { alertsService: AlertService; diff --git a/x-pack/plugins/cases/server/client/user_actions/client.ts b/x-pack/plugins/cases/server/client/user_actions/client.ts index f2e5edf255812..3f14a313cd8f2 100644 --- a/x-pack/plugins/cases/server/client/user_actions/client.ts +++ b/x-pack/plugins/cases/server/client/user_actions/client.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ICaseUserActionsResponse } from '../typedoc_interfaces'; -import { CasesClientArgs } from '../types'; +import type { ICaseUserActionsResponse } from '../typedoc_interfaces'; +import type { CasesClientArgs } from '../types'; import { get } from './get'; /** diff --git a/x-pack/plugins/cases/server/client/user_actions/get.ts b/x-pack/plugins/cases/server/client/user_actions/get.ts index d4b09eb39b583..835029315e434 100644 --- a/x-pack/plugins/cases/server/client/user_actions/get.ts +++ b/x-pack/plugins/cases/server/client/user_actions/get.ts @@ -5,16 +5,13 @@ * 2.0. */ -import { SavedObjectsFindResponse } from '@kbn/core/server'; -import { - CaseUserActionsResponse, - CaseUserActionsResponseRt, - CaseUserActionResponse, -} from '../../../common/api'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { CaseUserActionsResponse, CaseUserActionResponse } from '../../../common/api'; +import { CaseUserActionsResponseRt } from '../../../common/api'; import { createCaseError } from '../../common/error'; -import { CasesClientArgs } from '..'; +import type { CasesClientArgs } from '..'; import { Operations } from '../../authorization'; -import { UserActionGet } from './client'; +import type { UserActionGet } from './client'; export const get = async ( { caseId }: UserActionGet, diff --git a/x-pack/plugins/cases/server/client/user_profiles.mock.ts b/x-pack/plugins/cases/server/client/user_profiles.mock.ts index 80eaa8d844baa..fff45274914e7 100644 --- a/x-pack/plugins/cases/server/client/user_profiles.mock.ts +++ b/x-pack/plugins/cases/server/client/user_profiles.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfile } from '@kbn/security-plugin/common'; +import type { UserProfile } from '@kbn/security-plugin/common'; export const userProfiles: UserProfile[] = [ { diff --git a/x-pack/plugins/cases/server/client/utils.ts b/x-pack/plugins/cases/server/client/utils.ts index cfda2ead6545a..a23e300531f92 100644 --- a/x-pack/plugins/cases/server/client/utils.ts +++ b/x-pack/plugins/cases/server/client/utils.ts @@ -12,25 +12,28 @@ import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; -import { nodeBuilder, fromKueryExpression, KueryNode, escapeKuery } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; +import { nodeBuilder, fromKueryExpression, escapeKuery } from '@kbn/es-query'; import { isCommentRequestTypeExternalReference, isCommentRequestTypePersistableState, } from '../../common/utils/attachments'; import { CASE_SAVED_OBJECT } from '../../common/constants'; +import type { + CaseStatuses, + CommentRequest, + CaseSeverity, + CommentRequestExternalReferenceType, +} from '../../common/api'; import { OWNER_FIELD, AlertCommentRequestRt, ActionsCommentRequestRt, - CaseStatuses, - CommentRequest, ContextTypeUserRt, excess, throwErrors, - CaseSeverity, ExternalReferenceStorageType, ExternalReferenceSORt, - CommentRequestExternalReferenceType, ExternalReferenceNoSORt, PersistableStateAttachmentRt, } from '../../common/api'; @@ -42,8 +45,8 @@ import { isCommentRequestTypeActions, assertUnreachable, } from '../common/utils'; -import { SavedObjectFindOptionsKueryNode } from '../common/types'; -import { ConstructQueryParams } from './types'; +import type { SavedObjectFindOptionsKueryNode } from '../common/types'; +import type { ConstructQueryParams } from './types'; export const decodeCommentRequest = (comment: CommentRequest) => { if (isCommentRequestTypeUser(comment)) { diff --git a/x-pack/plugins/cases/server/common/error.ts b/x-pack/plugins/cases/server/common/error.ts index e994d249e858b..01b743ecfbe32 100644 --- a/x-pack/plugins/cases/server/common/error.ts +++ b/x-pack/plugins/cases/server/common/error.ts @@ -6,7 +6,7 @@ */ import { Boom, isBoom } from '@hapi/boom'; -import { Logger } from '@kbn/core/server'; +import type { Logger } from '@kbn/core/server'; export interface HTTPError extends Error { statusCode: number; diff --git a/x-pack/plugins/cases/server/common/models/case_with_comments.ts b/x-pack/plugins/cases/server/common/models/case_with_comments.ts index 9b695b2bbe9f6..2e5de37c621e2 100644 --- a/x-pack/plugins/cases/server/common/models/case_with_comments.ts +++ b/x-pack/plugins/cases/server/common/models/case_with_comments.ts @@ -6,33 +6,35 @@ */ import Boom from '@hapi/boom'; -import { +import type { SavedObject, SavedObjectReference, SavedObjectsUpdateOptions, SavedObjectsUpdateResponse, } from '@kbn/core/server'; -import { +import type { CaseResponse, - CaseResponseRt, - CaseStatuses, CommentAttributes, CommentPatchRequest, CommentRequest, - CommentType, CommentRequestUserType, CaseAttributes, + CommentRequestAlertType, +} from '../../../common/api'; +import { + CaseResponseRt, + CaseStatuses, + CommentType, ActionTypes, Actions, - CommentRequestAlertType, } from '../../../common/api'; import { CASE_SAVED_OBJECT, MAX_ALERTS_PER_CASE, MAX_DOCS_PER_PAGE, } from '../../../common/constants'; -import { CasesClientArgs } from '../../client'; -import { RefreshSetting } from '../../services/types'; +import type { CasesClientArgs } from '../../client'; +import type { RefreshSetting } from '../../services/types'; import { createCaseError } from '../error'; import { countAlertsForID, diff --git a/x-pack/plugins/cases/server/common/types.ts b/x-pack/plugins/cases/server/common/types.ts index 7a0d46148cf26..bb5c0d77b8201 100644 --- a/x-pack/plugins/cases/server/common/types.ts +++ b/x-pack/plugins/cases/server/common/types.ts @@ -6,7 +6,7 @@ */ import type { KueryNode } from '@kbn/es-query'; -import { SavedObjectFindOptions } from '../../common/api'; +import type { SavedObjectFindOptions } from '../../common/api'; /** * This structure holds the alert ID and index from an alert comment diff --git a/x-pack/plugins/cases/server/common/utils.test.ts b/x-pack/plugins/cases/server/common/utils.test.ts index 432fb0f92c4e6..cbf5b3e0cf5de 100644 --- a/x-pack/plugins/cases/server/common/utils.test.ts +++ b/x-pack/plugins/cases/server/common/utils.test.ts @@ -5,19 +5,17 @@ * 2.0. */ -import { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server'; +import type { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server'; import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; import { OWNER_INFO, SECURITY_SOLUTION_OWNER } from '../../common/constants'; -import { +import type { CaseConnector, CaseResponse, - CaseSeverity, CommentAttributes, CommentRequest, CommentRequestUserType, - CommentType, - ConnectorTypes, } from '../../common/api'; +import { CaseSeverity, CommentType, ConnectorTypes } from '../../common/api'; import { mockCaseComments, mockCases } from '../routes/api/__fixtures__/mock_saved_objects'; import { flattenCaseSavedObject, diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index 1c41ea53105c9..8a977c2f0e24b 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { SavedObjectsFindResult, SavedObjectsFindResponse, SavedObject, @@ -13,7 +13,7 @@ import { IBasePath, } from '@kbn/core/server'; import { flatMap, uniqWith, xorWith } from 'lodash'; -import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; import { isValidOwner } from '../../common/utils/owner'; import { CASE_VIEW_COMMENT_PATH, @@ -22,16 +22,14 @@ import { GENERAL_CASES_OWNER, OWNER_INFO, } from '../../common/constants'; -import { CASE_VIEW_PAGE_TABS } from '../../common/types'; -import { AlertInfo } from './types'; +import type { CASE_VIEW_PAGE_TABS } from '../../common/types'; +import type { AlertInfo } from './types'; -import { +import type { CaseAttributes, CasePostRequest, CaseResponse, - CaseSeverity, CasesFindResponse, - CaseStatuses, CommentAttributes, CommentRequest, CommentRequestActionsType, @@ -40,12 +38,16 @@ import { CommentRequestUserType, CommentResponse, CommentsResponse, + User, +} from '../../common/api'; +import { + CaseSeverity, + CaseStatuses, CommentType, ConnectorTypes, ExternalReferenceStorageType, - User, } from '../../common/api'; -import { UpdateAlertRequest } from '../client/alerts/types'; +import type { UpdateAlertRequest } from '../client/alerts/types'; import { parseCommentString, getLensVisualizations, diff --git a/x-pack/plugins/cases/server/config.ts b/x-pack/plugins/cases/server/config.ts index bbda9fa7a32ae..dc110412d1733 100644 --- a/x-pack/plugins/cases/server/config.ts +++ b/x-pack/plugins/cases/server/config.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { schema, TypeOf } from '@kbn/config-schema'; +import type { TypeOf } from '@kbn/config-schema'; +import { schema } from '@kbn/config-schema'; export const ConfigSchema = schema.object({ markdownPlugins: schema.object({ diff --git a/x-pack/plugins/cases/server/connectors/cases_webook/format.ts b/x-pack/plugins/cases/server/connectors/cases_webook/format.ts index 2356df109dd00..320b190dc24e8 100644 --- a/x-pack/plugins/cases/server/connectors/cases_webook/format.ts +++ b/x-pack/plugins/cases/server/connectors/cases_webook/format.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Format } from './types'; +import type { Format } from './types'; export const format: Format = (theCase) => { return { diff --git a/x-pack/plugins/cases/server/connectors/cases_webook/index.ts b/x-pack/plugins/cases/server/connectors/cases_webook/index.ts index 961e7648d0cef..118e1864eacc4 100644 --- a/x-pack/plugins/cases/server/connectors/cases_webook/index.ts +++ b/x-pack/plugins/cases/server/connectors/cases_webook/index.ts @@ -7,7 +7,7 @@ import { getMapping } from './mapping'; import { format } from './format'; -import { CasesWebhookCaseConnector } from './types'; +import type { CasesWebhookCaseConnector } from './types'; export const getCaseConnector = (): CasesWebhookCaseConnector => ({ getMapping, diff --git a/x-pack/plugins/cases/server/connectors/cases_webook/mapping.ts b/x-pack/plugins/cases/server/connectors/cases_webook/mapping.ts index 50bd66fdcec8c..5850af1d59f28 100644 --- a/x-pack/plugins/cases/server/connectors/cases_webook/mapping.ts +++ b/x-pack/plugins/cases/server/connectors/cases_webook/mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GetMapping } from './types'; +import type { GetMapping } from './types'; // Mappings are done directly in the connector configuration export const getMapping: GetMapping = () => []; diff --git a/x-pack/plugins/cases/server/connectors/cases_webook/types.ts b/x-pack/plugins/cases/server/connectors/cases_webook/types.ts index 61d74070370dc..4687e2be34a55 100644 --- a/x-pack/plugins/cases/server/connectors/cases_webook/types.ts +++ b/x-pack/plugins/cases/server/connectors/cases_webook/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ICasesConnector } from '../types'; +import type { ICasesConnector } from '../types'; export type CasesWebhookCaseConnector = ICasesConnector; export type Format = ICasesConnector['format']; diff --git a/x-pack/plugins/cases/server/connectors/factory.ts b/x-pack/plugins/cases/server/connectors/factory.ts index 40035fb984863..2f2287e288c54 100644 --- a/x-pack/plugins/cases/server/connectors/factory.ts +++ b/x-pack/plugins/cases/server/connectors/factory.ts @@ -6,7 +6,7 @@ */ import { ConnectorTypes } from '../../common/api'; -import { ICasesConnector, CasesConnectorsMap } from './types'; +import type { ICasesConnector, CasesConnectorsMap } from './types'; import { getCaseConnector as getJiraCaseConnector } from './jira'; import { getCaseConnector as getResilientCaseConnector } from './resilient'; import { getCaseConnector as getCasesWebhookCaseConnector } from './cases_webook'; diff --git a/x-pack/plugins/cases/server/connectors/jira/format.test.ts b/x-pack/plugins/cases/server/connectors/jira/format.test.ts index edca4cf68250c..7ddabdf5e2ff1 100644 --- a/x-pack/plugins/cases/server/connectors/jira/format.test.ts +++ b/x-pack/plugins/cases/server/connectors/jira/format.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseResponse } from '../../../common/api'; +import type { CaseResponse } from '../../../common/api'; import { format } from './format'; describe('Jira formatter', () => { diff --git a/x-pack/plugins/cases/server/connectors/jira/format.ts b/x-pack/plugins/cases/server/connectors/jira/format.ts index e283aff4b4ce9..47584b4ec2bba 100644 --- a/x-pack/plugins/cases/server/connectors/jira/format.ts +++ b/x-pack/plugins/cases/server/connectors/jira/format.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ConnectorJiraTypeFields } from '../../../common/api'; -import { Format } from './types'; +import type { ConnectorJiraTypeFields } from '../../../common/api'; +import type { Format } from './types'; export const format: Format = (theCase, alerts) => { const { diff --git a/x-pack/plugins/cases/server/connectors/jira/index.ts b/x-pack/plugins/cases/server/connectors/jira/index.ts index 9a2a00ac23b39..9fb891d9c23f4 100644 --- a/x-pack/plugins/cases/server/connectors/jira/index.ts +++ b/x-pack/plugins/cases/server/connectors/jira/index.ts @@ -7,7 +7,7 @@ import { getMapping } from './mapping'; import { format } from './format'; -import { JiraCaseConnector } from './types'; +import type { JiraCaseConnector } from './types'; export const getCaseConnector = (): JiraCaseConnector => ({ getMapping, diff --git a/x-pack/plugins/cases/server/connectors/jira/mapping.ts b/x-pack/plugins/cases/server/connectors/jira/mapping.ts index 8f8a914b4e091..716a2694bdf1a 100644 --- a/x-pack/plugins/cases/server/connectors/jira/mapping.ts +++ b/x-pack/plugins/cases/server/connectors/jira/mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GetMapping } from './types'; +import type { GetMapping } from './types'; export const getMapping: GetMapping = () => { return [ diff --git a/x-pack/plugins/cases/server/connectors/jira/types.ts b/x-pack/plugins/cases/server/connectors/jira/types.ts index 59d5741d381b9..95e9cf3059f14 100644 --- a/x-pack/plugins/cases/server/connectors/jira/types.ts +++ b/x-pack/plugins/cases/server/connectors/jira/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { JiraFieldsType } from '../../../common/api'; -import { ICasesConnector } from '../types'; +import type { JiraFieldsType } from '../../../common/api'; +import type { ICasesConnector } from '../types'; interface ExternalServiceFormatterParams extends JiraFieldsType { labels: string[]; diff --git a/x-pack/plugins/cases/server/connectors/resilient/format.test.ts b/x-pack/plugins/cases/server/connectors/resilient/format.test.ts index 5cfd089b9aa8d..cd850bd28fe37 100644 --- a/x-pack/plugins/cases/server/connectors/resilient/format.test.ts +++ b/x-pack/plugins/cases/server/connectors/resilient/format.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseResponse } from '../../../common/api'; +import type { CaseResponse } from '../../../common/api'; import { format } from './format'; describe('IBM Resilient formatter', () => { diff --git a/x-pack/plugins/cases/server/connectors/resilient/format.ts b/x-pack/plugins/cases/server/connectors/resilient/format.ts index 64b701731c33f..5cbec6b89dc23 100644 --- a/x-pack/plugins/cases/server/connectors/resilient/format.ts +++ b/x-pack/plugins/cases/server/connectors/resilient/format.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ConnectorResilientTypeFields } from '../../../common/api'; -import { Format } from './types'; +import type { ConnectorResilientTypeFields } from '../../../common/api'; +import type { Format } from './types'; export const format: Format = (theCase, alerts) => { const { incidentTypes = null, severityCode = null } = diff --git a/x-pack/plugins/cases/server/connectors/resilient/index.ts b/x-pack/plugins/cases/server/connectors/resilient/index.ts index a946d0d7fa1c5..bdd3962514d86 100644 --- a/x-pack/plugins/cases/server/connectors/resilient/index.ts +++ b/x-pack/plugins/cases/server/connectors/resilient/index.ts @@ -7,7 +7,7 @@ import { getMapping } from './mapping'; import { format } from './format'; -import { ResilientCaseConnector } from './types'; +import type { ResilientCaseConnector } from './types'; export const getCaseConnector = (): ResilientCaseConnector => ({ getMapping, diff --git a/x-pack/plugins/cases/server/connectors/resilient/mapping.ts b/x-pack/plugins/cases/server/connectors/resilient/mapping.ts index 0226073711dfb..d6e6642b6c4af 100644 --- a/x-pack/plugins/cases/server/connectors/resilient/mapping.ts +++ b/x-pack/plugins/cases/server/connectors/resilient/mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GetMapping } from './types'; +import type { GetMapping } from './types'; export const getMapping: GetMapping = () => { return [ diff --git a/x-pack/plugins/cases/server/connectors/resilient/types.ts b/x-pack/plugins/cases/server/connectors/resilient/types.ts index f895dccf65214..d3b64f8e139e6 100644 --- a/x-pack/plugins/cases/server/connectors/resilient/types.ts +++ b/x-pack/plugins/cases/server/connectors/resilient/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ResilientFieldsType } from '../../../common/api'; -import { ICasesConnector } from '../types'; +import type { ResilientFieldsType } from '../../../common/api'; +import type { ICasesConnector } from '../types'; export type ResilientCaseConnector = ICasesConnector; export type Format = ICasesConnector['format']; diff --git a/x-pack/plugins/cases/server/connectors/servicenow/index.ts b/x-pack/plugins/cases/server/connectors/servicenow/index.ts index e16a76ff5f79f..c1739790b342f 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/index.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/index.ts @@ -10,7 +10,7 @@ import { format as formatServiceNowITSM } from './itsm_format'; import { getMapping as getServiceNowSIRMapping } from './sir_mapping'; import { format as formatServiceNowSIR } from './sir_format'; -import { ServiceNowITSMCasesConnector, ServiceNowSIRCasesConnector } from './types'; +import type { ServiceNowITSMCasesConnector, ServiceNowSIRCasesConnector } from './types'; export const getServiceNowITSMCaseConnector = (): ServiceNowITSMCasesConnector => ({ getMapping: getServiceNowITSMMapping, diff --git a/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.test.ts b/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.test.ts index ac9dc8839bfb8..8db9ba7df4859 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.test.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseResponse } from '../../../common/api'; +import type { CaseResponse } from '../../../common/api'; import { format } from './itsm_format'; describe('ITSM formatter', () => { diff --git a/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.ts b/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.ts index 81a20d006c22e..cedbf81c71467 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/itsm_format.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ConnectorServiceNowITSMTypeFields } from '../../../common/api'; -import { ServiceNowITSMFormat } from './types'; +import type { ConnectorServiceNowITSMTypeFields } from '../../../common/api'; +import type { ServiceNowITSMFormat } from './types'; export const format: ServiceNowITSMFormat = (theCase, alerts) => { const { diff --git a/x-pack/plugins/cases/server/connectors/servicenow/itsm_mapping.ts b/x-pack/plugins/cases/server/connectors/servicenow/itsm_mapping.ts index a94d72576d6e3..50875a1736a7a 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/itsm_mapping.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/itsm_mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ServiceNowITSMGetMapping } from './types'; +import type { ServiceNowITSMGetMapping } from './types'; export const getMapping: ServiceNowITSMGetMapping = () => { return [ diff --git a/x-pack/plugins/cases/server/connectors/servicenow/sir_format.test.ts b/x-pack/plugins/cases/server/connectors/servicenow/sir_format.test.ts index 9b24dfa672bf4..6697aad205b92 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/sir_format.test.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/sir_format.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseResponse } from '../../../common/api'; +import type { CaseResponse } from '../../../common/api'; import { format } from './sir_format'; describe('SIR formatter', () => { diff --git a/x-pack/plugins/cases/server/connectors/servicenow/sir_format.ts b/x-pack/plugins/cases/server/connectors/servicenow/sir_format.ts index dae1045502460..8b686be473f6e 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/sir_format.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/sir_format.ts @@ -5,8 +5,8 @@ * 2.0. */ import { get } from 'lodash/fp'; -import { ConnectorServiceNowSIRTypeFields } from '../../../common/api'; -import { ServiceNowSIRFormat, SirFieldKey, AlertFieldMappingAndValues } from './types'; +import type { ConnectorServiceNowSIRTypeFields } from '../../../common/api'; +import type { ServiceNowSIRFormat, SirFieldKey, AlertFieldMappingAndValues } from './types'; export const format: ServiceNowSIRFormat = (theCase, alerts) => { const { diff --git a/x-pack/plugins/cases/server/connectors/servicenow/sir_mapping.ts b/x-pack/plugins/cases/server/connectors/servicenow/sir_mapping.ts index 04d9809bc8b99..2edf99ecb2a29 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/sir_mapping.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/sir_mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ServiceNowSIRGetMapping } from './types'; +import type { ServiceNowSIRGetMapping } from './types'; export const getMapping: ServiceNowSIRGetMapping = () => { return [ diff --git a/x-pack/plugins/cases/server/connectors/servicenow/types.ts b/x-pack/plugins/cases/server/connectors/servicenow/types.ts index 531786730ff9a..90fb336da7bac 100644 --- a/x-pack/plugins/cases/server/connectors/servicenow/types.ts +++ b/x-pack/plugins/cases/server/connectors/servicenow/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ServiceNowITSMFieldsType } from '../../../common/api'; -import { ICasesConnector } from '../types'; +import type { ServiceNowITSMFieldsType } from '../../../common/api'; +import type { ICasesConnector } from '../types'; interface CorrelationValues { correlation_id: string | null; diff --git a/x-pack/plugins/cases/server/connectors/swimlane/format.test.ts b/x-pack/plugins/cases/server/connectors/swimlane/format.test.ts index e72ca3d145c99..d3500c5f9e18e 100644 --- a/x-pack/plugins/cases/server/connectors/swimlane/format.test.ts +++ b/x-pack/plugins/cases/server/connectors/swimlane/format.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseResponse } from '../../../common/api'; +import type { CaseResponse } from '../../../common/api'; import { format } from './format'; describe('Swimlane formatter', () => { diff --git a/x-pack/plugins/cases/server/connectors/swimlane/format.ts b/x-pack/plugins/cases/server/connectors/swimlane/format.ts index 48983d745150b..ae8d7023f8f86 100644 --- a/x-pack/plugins/cases/server/connectors/swimlane/format.ts +++ b/x-pack/plugins/cases/server/connectors/swimlane/format.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ConnectorSwimlaneTypeFields } from '../../../common/api'; -import { Format } from './types'; +import type { ConnectorSwimlaneTypeFields } from '../../../common/api'; +import type { Format } from './types'; export const format: Format = (theCase) => { const { caseId = theCase.id } = diff --git a/x-pack/plugins/cases/server/connectors/swimlane/index.ts b/x-pack/plugins/cases/server/connectors/swimlane/index.ts index 2cad92391bdec..68ab5f65e86e3 100644 --- a/x-pack/plugins/cases/server/connectors/swimlane/index.ts +++ b/x-pack/plugins/cases/server/connectors/swimlane/index.ts @@ -7,7 +7,7 @@ import { getMapping } from './mapping'; import { format } from './format'; -import { SwimlaneCaseConnector } from './types'; +import type { SwimlaneCaseConnector } from './types'; export const getCaseConnector = (): SwimlaneCaseConnector => ({ getMapping, diff --git a/x-pack/plugins/cases/server/connectors/swimlane/mapping.ts b/x-pack/plugins/cases/server/connectors/swimlane/mapping.ts index e1e34054463e5..a5a1d7947074e 100644 --- a/x-pack/plugins/cases/server/connectors/swimlane/mapping.ts +++ b/x-pack/plugins/cases/server/connectors/swimlane/mapping.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { GetMapping } from './types'; +import type { GetMapping } from './types'; export const getMapping: GetMapping = () => { return [ diff --git a/x-pack/plugins/cases/server/connectors/swimlane/types.ts b/x-pack/plugins/cases/server/connectors/swimlane/types.ts index 22a1e9f6372d5..6d5788538fd11 100644 --- a/x-pack/plugins/cases/server/connectors/swimlane/types.ts +++ b/x-pack/plugins/cases/server/connectors/swimlane/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SwimlaneFieldsType } from '../../../common/api'; -import { ICasesConnector } from '../types'; +import type { SwimlaneFieldsType } from '../../../common/api'; +import type { ICasesConnector } from '../types'; export type SwimlaneCaseConnector = ICasesConnector; export type Format = ICasesConnector['format']; diff --git a/x-pack/plugins/cases/server/connectors/types.ts b/x-pack/plugins/cases/server/connectors/types.ts index 83dab22ec920f..b4cb6af0ddde9 100644 --- a/x-pack/plugins/cases/server/connectors/types.ts +++ b/x-pack/plugins/cases/server/connectors/types.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { Logger } from '@kbn/core/server'; -import { CaseResponse, ConnectorMappingsAttributes } from '../../common/api'; -import { CasesClientGetAlertsResponse } from '../client/alerts/types'; -import { CasesClientFactory } from '../client/factory'; -import { RegisterActionType } from '../types'; +import type { Logger } from '@kbn/core/server'; +import type { CaseResponse, ConnectorMappingsAttributes } from '../../common/api'; +import type { CasesClientGetAlertsResponse } from '../client/alerts/types'; +import type { CasesClientFactory } from '../client/factory'; +import type { RegisterActionType } from '../types'; export interface GetActionTypeParams { logger: Logger; diff --git a/x-pack/plugins/cases/server/features.ts b/x-pack/plugins/cases/server/features.ts index 9f92c7d9398a6..2573e5f58b3f3 100644 --- a/x-pack/plugins/cases/server/features.ts +++ b/x-pack/plugins/cases/server/features.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; -import { KibanaFeatureConfig } from '@kbn/features-plugin/common'; +import type { KibanaFeatureConfig } from '@kbn/features-plugin/common'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { APP_ID, FEATURE_ID } from '../common/constants'; diff --git a/x-pack/plugins/cases/server/index.ts b/x-pack/plugins/cases/server/index.ts index d6ac2b4657de8..ea2adeb1ca6d8 100644 --- a/x-pack/plugins/cases/server/index.ts +++ b/x-pack/plugins/cases/server/index.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; +import type { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server'; export { CasesClient } from './client'; -import { ConfigType, ConfigSchema } from './config'; +import type { ConfigType } from './config'; +import { ConfigSchema } from './config'; import { CasePlugin } from './plugin'; export const config: PluginConfigDescriptor = { diff --git a/x-pack/plugins/cases/server/plugin.ts b/x-pack/plugins/cases/server/plugin.ts index 2ca0c140f0202..7f06f34210c4e 100644 --- a/x-pack/plugins/cases/server/plugin.ts +++ b/x-pack/plugins/cases/server/plugin.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { IContextProvider, KibanaRequest, Logger, @@ -14,23 +14,23 @@ import { CoreStart, } from '@kbn/core/server'; -import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; -import { +import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { PluginSetupContract as ActionsPluginSetup, PluginStartContract as ActionsPluginStart, } from '@kbn/actions-plugin/server'; -import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; -import { +import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { PluginStartContract as FeaturesPluginStart, PluginSetupContract as FeaturesPluginSetup, } from '@kbn/features-plugin/server'; -import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; -import { +import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import type { TaskManagerSetupContract, TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { APP_ID } from '../common/constants'; import { @@ -42,7 +42,7 @@ import { casesTelemetrySavedObjectType, } from './saved_object_types'; -import { CasesClient } from './client'; +import type { CasesClient } from './client'; import type { CasesRequestHandlerContext, PluginSetupContract, PluginStartContract } from './types'; import { CasesClientFactory } from './client/factory'; import { getCasesKibanaFeature } from './features'; diff --git a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts index 1eb180edb09e4..d2eda3d6c9d73 100644 --- a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts +++ b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts @@ -5,15 +5,9 @@ * 2.0. */ -import { SavedObject } from '@kbn/core/server'; -import { - CaseAttributes, - CaseSeverity, - CaseStatuses, - CommentAttributes, - CommentType, - ConnectorTypes, -} from '../../../../common/api'; +import type { SavedObject } from '@kbn/core/server'; +import type { CaseAttributes, CommentAttributes } from '../../../../common/api'; +import { CaseSeverity, CaseStatuses, CommentType, ConnectorTypes } from '../../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants'; export const mockCases: Array> = [ diff --git a/x-pack/plugins/cases/server/routes/api/__mocks__/request_responses.ts b/x-pack/plugins/cases/server/routes/api/__mocks__/request_responses.ts index b398f9cfd1ba8..95724981c26fe 100644 --- a/x-pack/plugins/cases/server/routes/api/__mocks__/request_responses.ts +++ b/x-pack/plugins/cases/server/routes/api/__mocks__/request_responses.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { CasePostRequest, ConnectorTypes } from '../../../../common/api'; +import type { CasePostRequest } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../../common/constants'; export const newCase: CasePostRequest = { diff --git a/x-pack/plugins/cases/server/routes/api/cases/alerts/get_cases.ts b/x-pack/plugins/cases/server/routes/api/cases/alerts/get_cases.ts index 8a9c02cf574d7..14dfa6ad35b4f 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/alerts/get_cases.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/alerts/get_cases.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; -import { CasesByAlertIDRequest } from '../../../../../common/api'; +import type { CasesByAlertIDRequest } from '../../../../../common/api'; import { CASE_ALERTS_URL } from '../../../../../common/constants'; import { createCaseError } from '../../../../common/error'; import { createCasesRoute } from '../../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts b/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts index 2a42bb3fa3353..7d761e98a90db 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/find_cases.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesFindRequest } from '../../../../common/api'; +import type { CasesFindRequest } from '../../../../common/api'; import { CASES_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/patch_cases.ts b/x-pack/plugins/cases/server/routes/api/cases/patch_cases.ts index bb9649aaa092c..4bd0dcc12113c 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/patch_cases.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/patch_cases.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesPatchRequest } from '../../../../common/api'; +import type { CasesPatchRequest } from '../../../../common/api'; import { CASES_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/post_case.ts b/x-pack/plugins/cases/server/routes/api/cases/post_case.ts index 8c4d43274f21a..0ae9081c30851 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/post_case.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/post_case.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasePostRequest } from '../../../../common/api'; +import type { CasePostRequest } from '../../../../common/api'; import { CASES_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/push_case.ts b/x-pack/plugins/cases/server/routes/api/cases/push_case.ts index 9ee30ed34f2a5..a103d8847b20b 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/push_case.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/push_case.ts @@ -12,7 +12,7 @@ import { identity } from 'fp-ts/lib/function'; import { throwErrors, CasePushRequestParamsRt } from '../../../../common/api'; import { CASE_PUSH_URL } from '../../../../common/constants'; -import { CaseRoute } from '../types'; +import type { CaseRoute } from '../types'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/reporters/get_reporters.ts b/x-pack/plugins/cases/server/routes/api/cases/reporters/get_reporters.ts index 56465fd7be1c4..1dcdfea68b586 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/reporters/get_reporters.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/reporters/get_reporters.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AllReportersFindRequest } from '../../../../../common/api'; +import type { AllReportersFindRequest } from '../../../../../common/api'; import { CASE_REPORTERS_URL } from '../../../../../common/constants'; import { createCaseError } from '../../../../common/error'; import { createCasesRoute } from '../../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/cases/tags/get_tags.ts b/x-pack/plugins/cases/server/routes/api/cases/tags/get_tags.ts index 8c2071750f5e6..9a06cc29e72bd 100644 --- a/x-pack/plugins/cases/server/routes/api/cases/tags/get_tags.ts +++ b/x-pack/plugins/cases/server/routes/api/cases/tags/get_tags.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { AllTagsFindRequest } from '../../../../../common/api'; +import type { AllTagsFindRequest } from '../../../../../common/api'; import { CASE_TAGS_URL } from '../../../../../common/constants'; import { createCaseError } from '../../../../common/error'; import { createCasesRoute } from '../../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts b/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts index f501f3a425801..daef9f3fa9f04 100644 --- a/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts +++ b/x-pack/plugins/cases/server/routes/api/comments/post_comment.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { CASE_COMMENTS_URL } from '../../../../common/constants'; -import { CommentRequest } from '../../../../common/api'; +import type { CommentRequest } from '../../../../common/api'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/configure/get_configure.ts b/x-pack/plugins/cases/server/routes/api/configure/get_configure.ts index 72ca1f6a38324..d57c01a85dbc7 100644 --- a/x-pack/plugins/cases/server/routes/api/configure/get_configure.ts +++ b/x-pack/plugins/cases/server/routes/api/configure/get_configure.ts @@ -6,7 +6,7 @@ */ import { CASE_CONFIGURE_URL } from '../../../../common/constants'; -import { GetConfigureFindRequest } from '../../../../common/api'; +import type { GetConfigureFindRequest } from '../../../../common/api'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/configure/patch_configure.ts b/x-pack/plugins/cases/server/routes/api/configure/patch_configure.ts index b6754dc6da8f6..33190e769e5fb 100644 --- a/x-pack/plugins/cases/server/routes/api/configure/patch_configure.ts +++ b/x-pack/plugins/cases/server/routes/api/configure/patch_configure.ts @@ -10,12 +10,8 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { - CaseConfigureRequestParamsRt, - throwErrors, - CasesConfigurePatch, - excess, -} from '../../../../common/api'; +import type { CasesConfigurePatch } from '../../../../common/api'; +import { CaseConfigureRequestParamsRt, throwErrors, excess } from '../../../../common/api'; import { CASE_CONFIGURE_DETAILS_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/create_cases_route.ts b/x-pack/plugins/cases/server/routes/api/create_cases_route.ts index eb6a1079440a0..bb1cb25c6e166 100644 --- a/x-pack/plugins/cases/server/routes/api/create_cases_route.ts +++ b/x-pack/plugins/cases/server/routes/api/create_cases_route.ts @@ -5,6 +5,6 @@ * 2.0. */ -import { CaseRoute } from './types'; +import type { CaseRoute } from './types'; export const createCasesRoute = (route: CaseRoute) => route; diff --git a/x-pack/plugins/cases/server/routes/api/get_external_routes.ts b/x-pack/plugins/cases/server/routes/api/get_external_routes.ts index 7b7a18cc7c83c..d8a2a3d70e190 100644 --- a/x-pack/plugins/cases/server/routes/api/get_external_routes.ts +++ b/x-pack/plugins/cases/server/routes/api/get_external_routes.ts @@ -15,7 +15,7 @@ import { pushCaseRoute } from './cases/push_case'; import { getReportersRoute } from './cases/reporters/get_reporters'; import { getStatusRoute } from './stats/get_status'; import { getUserActionsRoute } from './user_actions/get_all_user_actions'; -import { CaseRoute } from './types'; +import type { CaseRoute } from './types'; import { getTagsRoute } from './cases/tags/get_tags'; import { deleteAllCommentsRoute } from './comments/delete_all_comments'; import { deleteCommentRoute } from './comments/delete_comment'; diff --git a/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts b/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts index 50e6bcf64cbd9..8f704d16e60e4 100644 --- a/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts +++ b/x-pack/plugins/cases/server/routes/api/get_internal_routes.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { UserProfileService } from '../../services'; +import type { UserProfileService } from '../../services'; import { bulkCreateAttachmentsRoute } from './internal/bulk_create_attachments'; import { suggestUserProfilesRoute } from './internal/suggest_user_profiles'; -import { CaseRoute } from './types'; +import type { CaseRoute } from './types'; export const getInternalRoutes = (userProfileService: UserProfileService) => [bulkCreateAttachmentsRoute, suggestUserProfilesRoute(userProfileService)] as CaseRoute[]; diff --git a/x-pack/plugins/cases/server/routes/api/internal/bulk_create_attachments.ts b/x-pack/plugins/cases/server/routes/api/internal/bulk_create_attachments.ts index cd2facd2391e3..a71d0fc10f649 100644 --- a/x-pack/plugins/cases/server/routes/api/internal/bulk_create_attachments.ts +++ b/x-pack/plugins/cases/server/routes/api/internal/bulk_create_attachments.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { INTERNAL_BULK_CREATE_ATTACHMENTS_URL } from '../../../../common/constants'; -import { BulkCreateCommentRequest } from '../../../../common/api'; +import type { BulkCreateCommentRequest } from '../../../../common/api'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; import { escapeHatch } from '../utils'; diff --git a/x-pack/plugins/cases/server/routes/api/internal/suggest_user_profiles.ts b/x-pack/plugins/cases/server/routes/api/internal/suggest_user_profiles.ts index 00a8d06259e22..0dc656e6e11e6 100644 --- a/x-pack/plugins/cases/server/routes/api/internal/suggest_user_profiles.ts +++ b/x-pack/plugins/cases/server/routes/api/internal/suggest_user_profiles.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfileService } from '../../../services'; +import type { UserProfileService } from '../../../services'; import { INTERNAL_SUGGEST_USER_PROFILES_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/register_routes.test.ts b/x-pack/plugins/cases/server/routes/api/register_routes.test.ts index 07aa3fc70a75f..f30387ca486f1 100644 --- a/x-pack/plugins/cases/server/routes/api/register_routes.test.ts +++ b/x-pack/plugins/cases/server/routes/api/register_routes.test.ts @@ -11,10 +11,10 @@ import { httpServerMock, httpServiceMock, loggingSystemMock } from '@kbn/core/se import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks'; -import { CasesRouter } from '../../types'; +import type { CasesRouter } from '../../types'; import { createCasesRoute } from './create_cases_route'; import { registerRoutes } from './register_routes'; -import { CaseRoute } from './types'; +import type { CaseRoute } from './types'; import { extractWarningValueFromWarningHeader } from './utils'; describe('registerRoutes', () => { diff --git a/x-pack/plugins/cases/server/routes/api/register_routes.ts b/x-pack/plugins/cases/server/routes/api/register_routes.ts index a9dcd51864a57..4a02e43fdae65 100644 --- a/x-pack/plugins/cases/server/routes/api/register_routes.ts +++ b/x-pack/plugins/cases/server/routes/api/register_routes.ts @@ -6,9 +6,9 @@ */ import { schema } from '@kbn/config-schema'; -import { Headers, RouteRegistrar } from '@kbn/core/server'; -import { CasesRequestHandlerContext } from '../../types'; -import { RegisterRoutesDeps } from './types'; +import type { Headers, RouteRegistrar } from '@kbn/core/server'; +import type { CasesRequestHandlerContext } from '../../types'; +import type { RegisterRoutesDeps } from './types'; import { escapeHatch, getIsKibanaRequest, diff --git a/x-pack/plugins/cases/server/routes/api/stats/get_status.ts b/x-pack/plugins/cases/server/routes/api/stats/get_status.ts index d35d366534c14..3fa4952559be4 100644 --- a/x-pack/plugins/cases/server/routes/api/stats/get_status.ts +++ b/x-pack/plugins/cases/server/routes/api/stats/get_status.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { CaseRoute } from '../types'; +import type { CaseRoute } from '../types'; -import { CasesStatusRequest } from '../../../../common/api'; +import type { CasesStatusRequest } from '../../../../common/api'; import { CASE_STATUS_URL } from '../../../../common/constants'; import { createCaseError } from '../../../common/error'; import { createCasesRoute } from '../create_cases_route'; diff --git a/x-pack/plugins/cases/server/routes/api/types.ts b/x-pack/plugins/cases/server/routes/api/types.ts index 3c340cec9ef2a..3dafad71b3cd8 100644 --- a/x-pack/plugins/cases/server/routes/api/types.ts +++ b/x-pack/plugins/cases/server/routes/api/types.ts @@ -14,7 +14,7 @@ import type { RouteValidatorConfig, } from '@kbn/core/server'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { CasesRequestHandlerContext, CasesRouter } from '../../types'; type TelemetryUsageCounter = ReturnType; diff --git a/x-pack/plugins/cases/server/routes/api/utils.test.ts b/x-pack/plugins/cases/server/routes/api/utils.test.ts index d7415276d3e71..68a6088309f7a 100644 --- a/x-pack/plugins/cases/server/routes/api/utils.test.ts +++ b/x-pack/plugins/cases/server/routes/api/utils.test.ts @@ -7,7 +7,7 @@ import { isBoom, boomify } from '@hapi/boom'; import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { HTTPError } from '../../common/error'; +import type { HTTPError } from '../../common/error'; import { extractWarningValueFromWarningHeader, logDeprecatedEndpoint, wrapError } from './utils'; describe('Utils', () => { diff --git a/x-pack/plugins/cases/server/routes/api/utils.ts b/x-pack/plugins/cases/server/routes/api/utils.ts index 3e595e74f042d..e363d37482a04 100644 --- a/x-pack/plugins/cases/server/routes/api/utils.ts +++ b/x-pack/plugins/cases/server/routes/api/utils.ts @@ -5,10 +5,12 @@ * 2.0. */ -import { Boom, boomify, isBoom } from '@hapi/boom'; +import type { Boom } from '@hapi/boom'; +import { boomify, isBoom } from '@hapi/boom'; import { schema } from '@kbn/config-schema'; import type { CustomHttpResponseOptions, ResponseError, Headers, Logger } from '@kbn/core/server'; -import { CaseError, isCaseError, HTTPError, isHTTPError } from '../../common/error'; +import type { CaseError, HTTPError } from '../../common/error'; +import { isCaseError, isHTTPError } from '../../common/error'; /** * Transforms an error into the correct format for a kibana response. diff --git a/x-pack/plugins/cases/server/saved_object_types/cases.ts b/x-pack/plugins/cases/server/saved_object_types/cases.ts index 8b50713c0e877..e0b9ab1cbafda 100644 --- a/x-pack/plugins/cases/server/saved_object_types/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/cases.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { CoreSetup, Logger, SavedObject, @@ -13,7 +13,7 @@ import { SavedObjectsType, } from '@kbn/core/server'; import { CASE_SAVED_OBJECT } from '../../common/constants'; -import { ESCaseAttributes } from '../services/cases/types'; +import type { ESCaseAttributes } from '../services/cases/types'; import { handleExport } from './import_export/export'; import { caseMigrations } from './migrations'; diff --git a/x-pack/plugins/cases/server/saved_object_types/comments.ts b/x-pack/plugins/cases/server/saved_object_types/comments.ts index 534cd0b006ee3..95df2007da00b 100644 --- a/x-pack/plugins/cases/server/saved_object_types/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/comments.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { SavedObjectsType } from '@kbn/core/server'; +import type { SavedObjectsType } from '@kbn/core/server'; import { CASE_COMMENT_SAVED_OBJECT } from '../../common/constants'; -import { createCommentsMigrations, CreateCommentsMigrationsDeps } from './migrations'; +import type { CreateCommentsMigrationsDeps } from './migrations'; +import { createCommentsMigrations } from './migrations'; export const createCaseCommentSavedObjectType = ({ migrationDeps, diff --git a/x-pack/plugins/cases/server/saved_object_types/configure.ts b/x-pack/plugins/cases/server/saved_object_types/configure.ts index 8e8744240719a..2ee1e3458c647 100644 --- a/x-pack/plugins/cases/server/saved_object_types/configure.ts +++ b/x-pack/plugins/cases/server/saved_object_types/configure.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsType } from '@kbn/core/server'; +import type { SavedObjectsType } from '@kbn/core/server'; import { CASE_CONFIGURE_SAVED_OBJECT } from '../../common/constants'; import { configureMigrations } from './migrations'; diff --git a/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts b/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts index a8d5ccf605158..7d89b090847d3 100644 --- a/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts +++ b/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsType } from '@kbn/core/server'; +import type { SavedObjectsType } from '@kbn/core/server'; import { CASE_CONNECTOR_MAPPINGS_SAVED_OBJECT } from '../../common/constants'; import { connectorMappingsMigrations } from './migrations'; diff --git a/x-pack/plugins/cases/server/saved_object_types/import_export/export.ts b/x-pack/plugins/cases/server/saved_object_types/import_export/export.ts index 78710558793fc..2e898c23d94b7 100644 --- a/x-pack/plugins/cases/server/saved_object_types/import_export/export.ts +++ b/x-pack/plugins/cases/server/saved_object_types/import_export/export.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { +import type { CoreSetup, Logger, SavedObject, SavedObjectsClientContract, SavedObjectsExportTransformContext, } from '@kbn/core/server'; -import { CaseUserActionAttributes, CommentAttributes } from '../../../common/api'; +import type { CaseUserActionAttributes, CommentAttributes } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, @@ -22,7 +22,7 @@ import { } from '../../../common/constants'; import { defaultSortField } from '../../common/utils'; import { createCaseError } from '../../common/error'; -import { ESCaseAttributes } from '../../services/cases/types'; +import type { ESCaseAttributes } from '../../services/cases/types'; export async function handleExport({ context, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts index 11eb477be73a5..c23bbd29dfe99 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts @@ -5,17 +5,13 @@ * 2.0. */ -import { SavedObjectSanitizedDoc } from '@kbn/core/server'; -import { - CaseAttributes, - CaseFullExternalService, - CaseSeverity, - ConnectorTypes, - NONE_CONNECTOR_ID, -} from '../../../common/api'; +import type { SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { CaseAttributes, CaseFullExternalService } from '../../../common/api'; +import { CaseSeverity, ConnectorTypes, NONE_CONNECTOR_ID } from '../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; -import { createExternalService, ESCaseConnectorWithId } from '../../services/test_utils'; +import type { ESCaseConnectorWithId } from '../../services/test_utils'; +import { createExternalService } from '../../services/test_utils'; import { addAssignees, addDuration, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts index 2e3672c6f72c2..50ea3e1dd8064 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts @@ -8,10 +8,12 @@ /* eslint-disable @typescript-eslint/naming-convention */ import { cloneDeep, unset } from 'lodash'; -import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; -import { addOwnerToSO, SanitizedCaseOwner } from '.'; -import { ESConnectorFields } from '../../services'; -import { CaseAttributes, CaseSeverity, ConnectorTypes } from '../../../common/api'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { SanitizedCaseOwner } from '.'; +import { addOwnerToSO } from '.'; +import type { ESConnectorFields } from '../../services'; +import type { CaseAttributes } from '../../../common/api'; +import { CaseSeverity, ConnectorTypes } from '../../../common/api'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts index 5804c0ff401dd..ed3273efd06af 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.test.ts @@ -20,18 +20,18 @@ import { CommentType } from '../../../common/api'; import { savedObjectsServiceMock } from '@kbn/core/server/mocks'; import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; -import { LensDocShape715 } from '@kbn/lens-plugin/server'; -import { - mergeSavedObjectMigrationMaps, +import type { LensDocShape715 } from '@kbn/lens-plugin/server'; +import type { SavedObjectReference, SavedObjectsMigrationLogger, SavedObjectUnsanitizedDoc, } from '@kbn/core/server'; -import { MigrateFunction, MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; -import { SerializableRecord } from '@kbn/utility-types'; +import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; +import type { MigrateFunction, MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; +import type { SerializableRecord } from '@kbn/utility-types'; import { GENERATED_ALERT, SUB_CASE_SAVED_OBJECT } from './constants'; import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; -import { PersistableStateAttachmentTypeSetup } from '../../attachment_framework/types'; +import type { PersistableStateAttachmentTypeSetup } from '../../attachment_framework/types'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; describe('comments migrations', () => { diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts index 5ab08d5e38040..b3978b6e12ef6 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/comments.ts @@ -7,30 +7,31 @@ import { mapValues, trimEnd, cloneDeep, unset } from 'lodash'; import type { SerializableRecord } from '@kbn/utility-types'; -import { MigrateFunction, MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; -import { +import type { MigrateFunction, MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc, SavedObjectMigrationFn, SavedObjectMigrationMap, SavedObjectMigrationContext, - mergeSavedObjectMigrationMaps, } from '@kbn/core/server'; -import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; -import { CommentAttributes, CommentType } from '../../../common/api'; +import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; +import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import type { CommentAttributes } from '../../../common/api'; +import { CommentType } from '../../../common/api'; +import type { LensMarkdownNode, MarkdownNode } from '../../../common/utils/markdown_plugins/utils'; import { isLensMarkdownNode, - LensMarkdownNode, - MarkdownNode, parseCommentString, stringifyMarkdownComment, } from '../../../common/utils/markdown_plugins/utils'; -import { addOwnerToSO, SanitizedCaseOwner } from '.'; +import type { SanitizedCaseOwner } from '.'; +import { addOwnerToSO } from '.'; import { logError } from './utils'; import { GENERATED_ALERT, SUB_CASE_SAVED_OBJECT } from './constants'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; import { getAllPersistableAttachmentMigrations } from './get_all_persistable_attachment_migrations'; -import { PersistableStateAttachmentState } from '../../attachment_framework/types'; +import type { PersistableStateAttachmentState } from '../../attachment_framework/types'; interface UnsanitizedComment { comment: string; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.test.ts index ac48732c07096..e42d75817c65b 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { SavedObjectSanitizedDoc } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; import { ConnectorTypes } from '../../../common/api'; import { CASE_CONFIGURE_SAVED_OBJECT, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { CONNECTOR_ID_REFERENCE_NAME } from '../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; -import { ESCaseConnectorWithId } from '../../services/test_utils'; -import { ESCasesConfigureAttributes } from '../../services/configure/types'; +import type { ESCaseConnectorWithId } from '../../services/test_utils'; +import type { ESCasesConfigureAttributes } from '../../services/configure/types'; import { configureConnectorIdMigration } from './configuration'; // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.ts index ebf0fc2dcfc19..84d1164ac23f1 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/configuration.ts @@ -7,9 +7,10 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; import { ConnectorTypes } from '../../../common/api'; -import { addOwnerToSO, SanitizedCaseOwner } from '.'; +import type { SanitizedCaseOwner } from '.'; +import { addOwnerToSO } from '.'; import { CONNECTOR_ID_REFERENCE_NAME } from '../../common/constants'; import { transformConnectorIdToReference } from './user_actions/connector_id'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.test.ts index 3ec108b84577c..4a4b4327881f2 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.test.ts @@ -6,7 +6,7 @@ */ import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; -import { PersistableStateAttachmentTypeSetup } from '../../attachment_framework/types'; +import type { PersistableStateAttachmentTypeSetup } from '../../attachment_framework/types'; import { getAllPersistableAttachmentMigrations } from './get_all_persistable_attachment_migrations'; describe('getAllPersistableAttachmentMigrations', () => { diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.ts index 7dfbb1517c7d5..ca074349c6768 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/get_all_persistable_attachment_migrations.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; -import { PersistableStateAttachmentState } from '../../attachment_framework/types'; +import type { MigrateFunctionsObject } from '@kbn/kibana-utils-plugin/common'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentState } from '../../attachment_framework/types'; const getMigrateFunction = ( persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts index 5ecf6c806065b..35d2e99906ba2 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; export { caseMigrations } from './cases'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.test.ts index 4542cbc269683..70cf329675126 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { SavedObject, SavedObjectMigrationContext, SavedObjectsMigrationLogger, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts index 8c5ad2b254b60..50e301a0945a8 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/alerts.ts @@ -5,15 +5,16 @@ * 2.0. */ -import { +import type { SavedObjectMigrationContext, SavedObjectSanitizedDoc, SavedObjectUnsanitizedDoc, } from '@kbn/core/server'; -import { CommentRequestAlertType, CommentType } from '../../../../common/api'; +import type { CommentRequestAlertType } from '../../../../common/api'; +import { CommentType } from '../../../../common/api'; import { GENERATED_ALERT } from '../constants'; import { logError } from '../utils'; -import { UserActionVersion800 } from './types'; +import type { UserActionVersion800 } from './types'; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/assignees.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/assignees.ts index d7b1110bbd5e1..9a3f0f766ad7e 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/assignees.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/assignees.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; -import { ActionTypes, CreateCaseUserAction } from '../../../../common/api'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { CreateCaseUserAction } from '../../../../common/api'; +import { ActionTypes } from '../../../../common/api'; export const addAssigneesToCreateUserAction = ( doc: SavedObjectUnsanitizedDoc diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.test.ts index a26581721eee6..ed43cc40649c6 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.test.ts @@ -7,7 +7,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { +import type { SavedObjectMigrationContext, SavedObjectSanitizedDoc, SavedObjectsMigrationLogger, @@ -24,7 +24,7 @@ import { createJiraConnector, } from '../../../services/test_utils'; import { userActionsConnectorIdMigration } from './connector_id'; -import { UserActions } from './types'; +import type { UserActions } from './types'; interface Pre810UserActionAttributes { new_value?: string; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.ts index c22b5f8c89479..b553d76da7f21 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/connector_id.ts @@ -7,18 +7,17 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import * as rt from 'io-ts'; +import type * as rt from 'io-ts'; -import { +import type { SavedObjectMigrationContext, SavedObjectReference, SavedObjectSanitizedDoc, SavedObjectUnsanitizedDoc, } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; +import type { CaseAttributes, CaseConnector } from '../../../../common/api'; import { - CaseAttributes, - CaseConnector, CaseConnectorRt, CaseExternalServiceBasicRt, NONE_CONNECTOR_ID, @@ -28,7 +27,7 @@ import { PUSH_CONNECTOR_ID_REFERENCE_NAME, } from '../../../common/constants'; import { getNoneCaseConnector } from '../../../common/utils'; -import { UserActionVersion800 } from './types'; +import type { UserActionVersion800 } from './types'; import { logError } from '../utils'; import { USER_ACTION_OLD_ID_REF_NAME, USER_ACTION_OLD_PUSH_ID_REF_NAME } from './constants'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/index.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/index.ts index 98a1e2454ffc4..e152cb6d386b0 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/index.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/index.ts @@ -7,30 +7,27 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc, SavedObjectMigrationMap, - mergeSavedObjectMigrationMaps, SavedObjectMigrationFn, } from '@kbn/core/server'; +import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; -import { MigrateFunctionsObject, MigrateFunction } from '@kbn/kibana-utils-plugin/common'; +import type { MigrateFunctionsObject, MigrateFunction } from '@kbn/kibana-utils-plugin/common'; import { mapValues } from 'lodash'; -import { PersistableStateAttachmentState } from '../../../attachment_framework/types'; -import { - ActionTypes, - CaseUserActionAttributes, - CommentType, - ConnectorTypes, -} from '../../../../common/api'; -import { PersistableStateAttachmentTypeRegistry } from '../../../attachment_framework/persistable_state_registry'; -import { addOwnerToSO, SanitizedCaseOwner } from '..'; +import type { PersistableStateAttachmentState } from '../../../attachment_framework/types'; +import type { CaseUserActionAttributes } from '../../../../common/api'; +import { ActionTypes, CommentType, ConnectorTypes } from '../../../../common/api'; +import type { PersistableStateAttachmentTypeRegistry } from '../../../attachment_framework/persistable_state_registry'; +import type { SanitizedCaseOwner } from '..'; +import { addOwnerToSO } from '..'; import { removeRuleInformation } from './alerts'; import { userActionsConnectorIdMigration } from './connector_id'; import { payloadMigration } from './payload'; import { addSeverityToCreateUserAction } from './severity'; -import { UserActions } from './types'; +import type { UserActions } from './types'; import { getAllPersistableAttachmentMigrations } from '../get_all_persistable_attachment_migrations'; import { addAssigneesToCreateUserAction } from './assignees'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.test.ts index 7ac7711b79db3..b4980be136c81 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.test.ts @@ -7,7 +7,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; +import type { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; import { migrationMocks } from '@kbn/core/server/mocks'; import { CommentType } from '../../../../common/api'; import { @@ -16,7 +16,7 @@ import { } from '../../../../common/constants'; import { createJiraConnector } from '../../../services/test_utils'; import { payloadMigration } from './payload'; -import { UserActions } from './types'; +import type { UserActions } from './types'; const create_7_14_0_userAction = (params: { action: string; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.ts index 0a04c858e7d4d..cd1ef23f86223 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/payload.ts @@ -9,23 +9,18 @@ import { isEmpty, isPlainObject, isString } from 'lodash'; -import { +import type { SavedObjectMigrationContext, SavedObjectReference, SavedObjectSanitizedDoc, SavedObjectUnsanitizedDoc, } from '@kbn/core/server'; -import { - Actions, - ActionTypes, - CaseStatuses, - CommentType, - UserActionTypes, -} from '../../../../common/api'; +import type { UserActionTypes } from '../../../../common/api'; +import { Actions, ActionTypes, CaseStatuses, CommentType } from '../../../../common/api'; import { USER_ACTION_OLD_ID_REF_NAME, USER_ACTION_OLD_PUSH_ID_REF_NAME } from './constants'; import { getNoneCaseConnector } from '../../../common/utils'; import { logError } from '../utils'; -import { UserActions } from './types'; +import type { UserActions } from './types'; export function payloadMigration( doc: SavedObjectUnsanitizedDoc, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/severity.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/severity.ts index 6e838e7bcbc1d..1e37a055bb0bb 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/severity.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/user_actions/severity.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; -import { ActionTypes, CaseSeverity, CreateCaseUserAction } from '../../../../common/api'; +import type { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; +import type { CreateCaseUserAction } from '../../../../common/api'; +import { ActionTypes, CaseSeverity } from '../../../../common/api'; export const addSeverityToCreateUserAction = ( doc: SavedObjectUnsanitizedDoc diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.test.ts index 3284c09df274f..a81cd40cb2c15 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsMigrationLogger } from '@kbn/core/server'; +import type { SavedObjectsMigrationLogger } from '@kbn/core/server'; import { migrationMocks } from '@kbn/core/server/mocks'; import { logError } from './utils'; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts index 8996f89155949..3b3a7c8e50792 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts @@ -5,7 +5,11 @@ * 2.0. */ -import { LogMeta, SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; +import type { + LogMeta, + SavedObjectMigrationContext, + SavedObjectUnsanitizedDoc, +} from '@kbn/core/server'; interface MigrationLogMeta extends LogMeta { migrations: { diff --git a/x-pack/plugins/cases/server/saved_object_types/telemetry.ts b/x-pack/plugins/cases/server/saved_object_types/telemetry.ts index 932fc39a6b180..515d1e63c7858 100644 --- a/x-pack/plugins/cases/server/saved_object_types/telemetry.ts +++ b/x-pack/plugins/cases/server/saved_object_types/telemetry.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsType } from '@kbn/core/server'; +import type { SavedObjectsType } from '@kbn/core/server'; import { CASE_TELEMETRY_SAVED_OBJECT } from '../../common/constants'; export const casesTelemetrySavedObjectType: SavedObjectsType = { diff --git a/x-pack/plugins/cases/server/saved_object_types/user_actions.ts b/x-pack/plugins/cases/server/saved_object_types/user_actions.ts index bc6e61ba05ded..1862e180acc22 100644 --- a/x-pack/plugins/cases/server/saved_object_types/user_actions.ts +++ b/x-pack/plugins/cases/server/saved_object_types/user_actions.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { SavedObjectsType } from '@kbn/core/server'; +import type { SavedObjectsType } from '@kbn/core/server'; import { CASE_USER_ACTION_SAVED_OBJECT } from '../../common/constants'; -import { createUserActionsMigrations, UserActionsMigrationsDeps } from './migrations/user_actions'; +import type { UserActionsMigrationsDeps } from './migrations/user_actions'; +import { createUserActionsMigrations } from './migrations/user_actions'; export const createCaseUserActionSavedObjectType = ( migrationDeps: UserActionsMigrationsDeps diff --git a/x-pack/plugins/cases/server/services/alerts/index.ts b/x-pack/plugins/cases/server/services/alerts/index.ts index a83528d026fd0..3a36d85fb0288 100644 --- a/x-pack/plugins/cases/server/services/alerts/index.ts +++ b/x-pack/plugins/cases/server/services/alerts/index.ts @@ -8,18 +8,16 @@ import pMap from 'p-map'; import { isEmpty } from 'lodash'; -import { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { - ALERT_WORKFLOW_STATUS, - STATUS_VALUES, -} from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; -import { MgetResponse } from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient, Logger } from '@kbn/core/server'; +import type { STATUS_VALUES } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; +import type { MgetResponse } from '@elastic/elasticsearch/lib/api/types'; import { CaseStatuses } from '../../../common/api'; import { MAX_ALERTS_PER_CASE, MAX_CONCURRENT_SEARCHES } from '../../../common/constants'; import { createCaseError } from '../../common/error'; -import { AlertInfo } from '../../common/types'; -import { UpdateAlertRequest } from '../../client/alerts/types'; -import { AggregationBuilder, AggregationResponse } from '../../client/metrics/types'; +import type { AlertInfo } from '../../common/types'; +import type { UpdateAlertRequest } from '../../client/alerts/types'; +import type { AggregationBuilder, AggregationResponse } from '../../client/metrics/types'; export class AlertService { constructor( diff --git a/x-pack/plugins/cases/server/services/attachments/index.ts b/x-pack/plugins/cases/server/services/attachments/index.ts index aa055663d6e03..e12ff71a20cf9 100644 --- a/x-pack/plugins/cases/server/services/attachments/index.ts +++ b/x-pack/plugins/cases/server/services/attachments/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { Logger, SavedObject, SavedObjectReference, @@ -19,30 +19,30 @@ import { import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { KueryNode } from '@kbn/es-query'; -import { +import type { AttributesTypeAlerts, CommentAttributes as AttachmentAttributes, CommentAttributesWithoutRefs as AttachmentAttributesWithoutRefs, CommentPatchAttributes as AttachmentPatchAttributes, - CommentType, } from '../../../common/api'; +import { CommentType } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, MAX_DOCS_PER_PAGE, } from '../../../common/constants'; -import { ClientArgs } from '..'; +import type { ClientArgs } from '..'; import { buildFilter, combineFilters } from '../../client/utils'; import { defaultSortField } from '../../common/utils'; -import { AggregationResponse } from '../../client/metrics/types'; +import type { AggregationResponse } from '../../client/metrics/types'; import { extractAttachmentSORefsFromAttributes, injectAttachmentSOAttributesFromRefs, injectAttachmentSOAttributesFromRefsForPatch, } from '../so_references'; -import { SavedObjectFindOptionsKueryNode } from '../../common/types'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; -import { IndexRefresh } from '../types'; +import type { SavedObjectFindOptionsKueryNode } from '../../common/types'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { IndexRefresh } from '../types'; interface AttachedToCaseArgs extends ClientArgs { caseId: string; diff --git a/x-pack/plugins/cases/server/services/cases/index.test.ts b/x-pack/plugins/cases/server/services/cases/index.test.ts index b5902778ae73d..1043d456f5cae 100644 --- a/x-pack/plugins/cases/server/services/cases/index.test.ts +++ b/x-pack/plugins/cases/server/services/cases/index.test.ts @@ -13,10 +13,10 @@ * connector.id. */ -import { CaseAttributes, CaseConnector, CaseFullExternalService } from '../../../common/api'; +import type { CaseAttributes, CaseConnector, CaseFullExternalService } from '../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { +import type { SavedObject, SavedObjectReference, SavedObjectsCreateOptions, @@ -30,17 +30,17 @@ import { loggerMock } from '@kbn/logging-mocks'; import { CONNECTOR_ID_REFERENCE_NAME } from '../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; import { CasesService } from '.'; +import type { ESCaseConnectorWithId } from '../test_utils'; import { createESJiraConnector, createJiraConnector, - ESCaseConnectorWithId, createExternalService, createSavedObjectReferences, createCaseSavedObjectResponse, basicCaseFields, createSOFindResponse, } from '../test_utils'; -import { ESCaseAttributes } from './types'; +import type { ESCaseAttributes } from './types'; import { AttachmentService } from '../attachments'; import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; diff --git a/x-pack/plugins/cases/server/services/cases/index.ts b/x-pack/plugins/cases/server/services/cases/index.ts index 2577365f2a25b..8b0a5e70f925e 100644 --- a/x-pack/plugins/cases/server/services/cases/index.ts +++ b/x-pack/plugins/cases/server/services/cases/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { Logger, SavedObject, SavedObjectsClientContract, @@ -19,14 +19,15 @@ import { } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { nodeBuilder, KueryNode } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; +import { nodeBuilder } from '@kbn/es-query'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, MAX_DOCS_PER_PAGE, } from '../../../common/constants'; -import { +import type { GetCaseIdsByAlertIdAggs, CaseResponse, CasesFindRequest, @@ -34,9 +35,9 @@ import { User, CaseAttributes, CaseStatuses, - caseStatuses, } from '../../../common/api'; -import { SavedObjectFindOptionsKueryNode } from '../../common/types'; +import { caseStatuses } from '../../../common/api'; +import type { SavedObjectFindOptionsKueryNode } from '../../common/types'; import { defaultSortField, flattenCaseSavedObject } from '../../common/utils'; import { DEFAULT_PAGE, DEFAULT_PER_PAGE } from '../../routes/api'; import { combineFilters } from '../../client/utils'; @@ -49,11 +50,11 @@ import { transformBulkResponseToExternalModel, transformFindResponseToExternalModel, } from './transform'; -import { ESCaseAttributes } from './types'; -import { AttachmentService } from '../attachments'; -import { AggregationBuilder, AggregationResponse } from '../../client/metrics/types'; +import type { ESCaseAttributes } from './types'; +import type { AttachmentService } from '../attachments'; +import type { AggregationBuilder, AggregationResponse } from '../../client/metrics/types'; import { createCaseError } from '../../common/error'; -import { IndexRefresh } from '../types'; +import type { IndexRefresh } from '../types'; interface GetCaseIdsByAlertIdArgs { alertId: string; diff --git a/x-pack/plugins/cases/server/services/cases/transform.ts b/x-pack/plugins/cases/server/services/cases/transform.ts index c013475bd2e9c..1b66ff41df421 100644 --- a/x-pack/plugins/cases/server/services/cases/transform.ts +++ b/x-pack/plugins/cases/server/services/cases/transform.ts @@ -7,7 +7,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import { +import type { SavedObject, SavedObjectReference, SavedObjectsBulkResponse, @@ -16,12 +16,13 @@ import { SavedObjectsUpdateResponse, } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { ESCaseAttributes, ExternalServicesWithoutConnectorId } from './types'; +import type { ESCaseAttributes, ExternalServicesWithoutConnectorId } from './types'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, } from '../../common/constants'; -import { CaseAttributes, CaseFullExternalService, NONE_CONNECTOR_ID } from '../../../common/api'; +import type { CaseAttributes, CaseFullExternalService } from '../../../common/api'; +import { NONE_CONNECTOR_ID } from '../../../common/api'; import { findConnectorIdReference, transformFieldsToESModel, diff --git a/x-pack/plugins/cases/server/services/cases/types.ts b/x-pack/plugins/cases/server/services/cases/types.ts index eb47850eeef31..db7b51f3eda3a 100644 --- a/x-pack/plugins/cases/server/services/cases/types.ts +++ b/x-pack/plugins/cases/server/services/cases/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import * as rt from 'io-ts'; -import { CaseAttributes, CaseExternalServiceBasicRt } from '../../../common/api'; -import { ESCaseConnector } from '..'; +import type * as rt from 'io-ts'; +import type { CaseAttributes, CaseExternalServiceBasicRt } from '../../../common/api'; +import type { ESCaseConnector } from '..'; /** * This type should only be used within the cases service and its helper functions (e.g. the transforms). diff --git a/x-pack/plugins/cases/server/services/configure/index.test.ts b/x-pack/plugins/cases/server/services/configure/index.test.ts index b967886b13be9..6c65aaab70828 100644 --- a/x-pack/plugins/cases/server/services/configure/index.test.ts +++ b/x-pack/plugins/cases/server/services/configure/index.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { +import type { CaseConnector, CasesConfigureAttributes, CasesConfigurePatch, - ConnectorTypes, } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; import { CASE_CONFIGURE_SAVED_OBJECT, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { +import type { SavedObject, SavedObjectReference, SavedObjectsCreateOptions, @@ -24,10 +24,11 @@ import { import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; import { loggerMock } from '@kbn/logging-mocks'; import { CaseConfigureService } from '.'; -import { ESCasesConfigureAttributes } from './types'; +import type { ESCasesConfigureAttributes } from './types'; import { CONNECTOR_ID_REFERENCE_NAME } from '../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; -import { createESJiraConnector, createJiraConnector, ESCaseConnectorWithId } from '../test_utils'; +import type { ESCaseConnectorWithId } from '../test_utils'; +import { createESJiraConnector, createJiraConnector } from '../test_utils'; const basicConfigFields = { closure_type: 'close-by-pushing' as const, diff --git a/x-pack/plugins/cases/server/services/configure/index.ts b/x-pack/plugins/cases/server/services/configure/index.ts index 4cd7f5ad7283f..8a63f1fcfce2f 100644 --- a/x-pack/plugins/cases/server/services/configure/index.ts +++ b/x-pack/plugins/cases/server/services/configure/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { Logger, SavedObject, SavedObjectsClientContract, @@ -14,9 +14,9 @@ import { } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { SavedObjectFindOptionsKueryNode } from '../../common/types'; +import type { SavedObjectFindOptionsKueryNode } from '../../common/types'; import { CONNECTOR_ID_REFERENCE_NAME } from '../../common/constants'; -import { CasesConfigureAttributes, CasesConfigurePatch } from '../../../common/api'; +import type { CasesConfigureAttributes, CasesConfigurePatch } from '../../../common/api'; import { CASE_CONFIGURE_SAVED_OBJECT } from '../../../common/constants'; import { transformFieldsToESModel, @@ -24,8 +24,8 @@ import { transformESConnectorOrUseDefault, } from '../transform'; import { ConnectorReferenceHandler } from '../connector_reference_handler'; -import { ESCasesConfigureAttributes } from './types'; -import { IndexRefresh } from '../types'; +import type { ESCasesConfigureAttributes } from './types'; +import type { IndexRefresh } from '../types'; interface ClientArgs { unsecuredSavedObjectsClient: SavedObjectsClientContract; diff --git a/x-pack/plugins/cases/server/services/configure/types.ts b/x-pack/plugins/cases/server/services/configure/types.ts index 3c4405e532e69..4e6ecc03955ae 100644 --- a/x-pack/plugins/cases/server/services/configure/types.ts +++ b/x-pack/plugins/cases/server/services/configure/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { CasesConfigureAttributes } from '../../../common/api'; -import { ESCaseConnector } from '..'; +import type { CasesConfigureAttributes } from '../../../common/api'; +import type { ESCaseConnector } from '..'; /** * This type should only be used within the configure service. It represents how the configure saved object will be layed diff --git a/x-pack/plugins/cases/server/services/connector_mappings/index.ts b/x-pack/plugins/cases/server/services/connector_mappings/index.ts index 2163775bf50ef..3f0c2d64260a7 100644 --- a/x-pack/plugins/cases/server/services/connector_mappings/index.ts +++ b/x-pack/plugins/cases/server/services/connector_mappings/index.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { Logger, SavedObjectReference, SavedObjectsClientContract } from '@kbn/core/server'; +import type { Logger, SavedObjectReference, SavedObjectsClientContract } from '@kbn/core/server'; import { CASE_CONNECTOR_MAPPINGS_SAVED_OBJECT } from '../../../common/constants'; -import { ConnectorMappings } from '../../../common/api'; -import { SavedObjectFindOptionsKueryNode } from '../../common/types'; -import { IndexRefresh } from '../types'; +import type { ConnectorMappings } from '../../../common/api'; +import type { SavedObjectFindOptionsKueryNode } from '../../common/types'; +import type { IndexRefresh } from '../types'; interface ClientArgs { unsecuredSavedObjectsClient: SavedObjectsClientContract; diff --git a/x-pack/plugins/cases/server/services/connector_reference_handler.ts b/x-pack/plugins/cases/server/services/connector_reference_handler.ts index f11c3317f690e..327dac42b6b70 100644 --- a/x-pack/plugins/cases/server/services/connector_reference_handler.ts +++ b/x-pack/plugins/cases/server/services/connector_reference_handler.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectReference } from '@kbn/core/server'; +import type { SavedObjectReference } from '@kbn/core/server'; import { NONE_CONNECTOR_ID } from '../../common/api'; interface Reference { diff --git a/x-pack/plugins/cases/server/services/index.ts b/x-pack/plugins/cases/server/services/index.ts index 5ba4fe74603e6..e15584b6ced9e 100644 --- a/x-pack/plugins/cases/server/services/index.ts +++ b/x-pack/plugins/cases/server/services/index.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { SavedObjectsClientContract } from '@kbn/core/server'; -import { ConnectorTypes } from '../../common/api'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { ConnectorTypes } from '../../common/api'; export { CasesService } from './cases'; export { CaseConfigureService } from './configure'; diff --git a/x-pack/plugins/cases/server/services/licensing.ts b/x-pack/plugins/cases/server/services/licensing.ts index 0b323150a72af..0902d400a417a 100644 --- a/x-pack/plugins/cases/server/services/licensing.ts +++ b/x-pack/plugins/cases/server/services/licensing.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { firstValueFrom, Observable } from 'rxjs'; -import { ILicense, LicenseType, LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { Observable } from 'rxjs'; +import { firstValueFrom } from 'rxjs'; +import type { ILicense, LicenseType, LicensingPluginStart } from '@kbn/licensing-plugin/server'; export class LicensingService { private readonly license$: Observable; diff --git a/x-pack/plugins/cases/server/services/mocks.ts b/x-pack/plugins/cases/server/services/mocks.ts index d157a5b332a96..6ef9af3f36a1b 100644 --- a/x-pack/plugins/cases/server/services/mocks.ts +++ b/x-pack/plugins/cases/server/services/mocks.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { PublicMethodsOf } from '@kbn/utility-types'; -import { +import type { PublicMethodsOf } from '@kbn/utility-types'; +import type { AlertService, CaseConfigureService, CasesService, diff --git a/x-pack/plugins/cases/server/services/so_reference_extractor.test.ts b/x-pack/plugins/cases/server/services/so_reference_extractor.test.ts index 223c9dbc5912c..1592a49c1189a 100644 --- a/x-pack/plugins/cases/server/services/so_reference_extractor.test.ts +++ b/x-pack/plugins/cases/server/services/so_reference_extractor.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObject, SavedObjectReference } from '@kbn/core/server'; +import type { SavedObject, SavedObjectReference } from '@kbn/core/server'; import { SOReferenceExtractor } from './so_reference_extractor'; describe('SOReferenceExtractor', () => { diff --git a/x-pack/plugins/cases/server/services/so_reference_extractor.ts b/x-pack/plugins/cases/server/services/so_reference_extractor.ts index 27fdf17b5f727..79414659661b8 100644 --- a/x-pack/plugins/cases/server/services/so_reference_extractor.ts +++ b/x-pack/plugins/cases/server/services/so_reference_extractor.ts @@ -7,7 +7,11 @@ import { set } from '@kbn/safer-lodash-set'; import _ from 'lodash'; -import { SavedObject, SavedObjectReference, SavedObjectsUpdateResponse } from '@kbn/core/server'; +import type { + SavedObject, + SavedObjectReference, + SavedObjectsUpdateResponse, +} from '@kbn/core/server'; interface Field { path: string; diff --git a/x-pack/plugins/cases/server/services/so_references.ts b/x-pack/plugins/cases/server/services/so_references.ts index ef439ac4281e2..d5dcc50da03e3 100644 --- a/x-pack/plugins/cases/server/services/so_references.ts +++ b/x-pack/plugins/cases/server/services/so_references.ts @@ -5,17 +5,17 @@ * 2.0. */ -import { SavedObjectsUpdateResponse } from '@kbn/core/server'; -import { SavedObject, SavedObjectReference } from '@kbn/core/types'; +import type { SavedObjectsUpdateResponse } from '@kbn/core/server'; +import type { SavedObject, SavedObjectReference } from '@kbn/core/types'; import { isEqual, uniqWith } from 'lodash'; -import { +import type { CommentAttributesNoSO, CommentRequest, CommentAttributes, CommentPatchAttributes, CommentAttributesWithoutRefs, } from '../../common/api'; -import { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../attachment_framework/persistable_state_registry'; import { injectPersistableReferencesToSO, extractPersistableStateReferencesFromSO, diff --git a/x-pack/plugins/cases/server/services/test_utils.ts b/x-pack/plugins/cases/server/services/test_utils.ts index 8206eee3515e3..70266c1a74635 100644 --- a/x-pack/plugins/cases/server/services/test_utils.ts +++ b/x-pack/plugins/cases/server/services/test_utils.ts @@ -5,22 +5,19 @@ * 2.0. */ -import { SavedObject, SavedObjectReference, SavedObjectsFindResult } from '@kbn/core/server'; +import type { SavedObject, SavedObjectReference, SavedObjectsFindResult } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { ESConnectorFields } from '.'; +import type { ESConnectorFields } from '.'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME } from '../common/constants'; -import { +import type { CaseAttributes, CaseConnector, CaseExternalServiceBasic, CaseFullExternalService, - CaseSeverity, - CaseStatuses, - ConnectorTypes, - NONE_CONNECTOR_ID, } from '../../common/api'; +import { CaseSeverity, CaseStatuses, ConnectorTypes, NONE_CONNECTOR_ID } from '../../common/api'; import { CASE_SAVED_OBJECT, SECURITY_SOLUTION_OWNER } from '../../common/constants'; -import { ESCaseAttributes, ExternalServicesWithoutConnectorId } from './cases/types'; +import type { ESCaseAttributes, ExternalServicesWithoutConnectorId } from './cases/types'; import { getNoneCaseConnector } from '../common/utils'; /** diff --git a/x-pack/plugins/cases/server/services/transform.ts b/x-pack/plugins/cases/server/services/transform.ts index e8467a9031f13..50d5192610d4f 100644 --- a/x-pack/plugins/cases/server/services/transform.ts +++ b/x-pack/plugins/cases/server/services/transform.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SavedObjectReference } from '@kbn/core/server'; +import type { SavedObjectReference } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { CaseConnector, ConnectorTypeFields } from '../../common/api'; +import type { CaseConnector, ConnectorTypeFields } from '../../common/api'; import { getNoneCaseConnector } from '../common/utils'; -import { ESCaseConnector, ESConnectorFields } from '.'; +import type { ESCaseConnector, ESConnectorFields } from '.'; export function findConnectorIdReference( name: string, diff --git a/x-pack/plugins/cases/server/services/types.ts b/x-pack/plugins/cases/server/services/types.ts index 1df1158583fa4..a9bf41e875e6c 100644 --- a/x-pack/plugins/cases/server/services/types.ts +++ b/x-pack/plugins/cases/server/services/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectsCreateOptions } from '@kbn/core/server'; +import type { SavedObjectsCreateOptions } from '@kbn/core/server'; export type RefreshSetting = NonNullable; diff --git a/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts b/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts index 2f66de0b5bb82..30f66bd9ece67 100644 --- a/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts +++ b/x-pack/plugins/cases/server/services/user_actions/abstract_builder.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SavedObjectReference } from '@kbn/core/server'; +import type { SavedObjectReference } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../../common/constants'; import { @@ -14,21 +14,16 @@ import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, } from '../../common/constants'; -import { - ActionTypes, - CaseConnector, - CaseExternalServiceBasic, - NONE_CONNECTOR_ID, - User, -} from '../../../common/api'; -import { +import type { CaseConnector, CaseExternalServiceBasic, User } from '../../../common/api'; +import { ActionTypes, NONE_CONNECTOR_ID } from '../../../common/api'; +import type { BuilderDeps, BuilderParameters, BuilderReturnValue, CommonBuilderArguments, UserActionParameters, } from './types'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; export abstract class UserActionBuilder { protected readonly persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; diff --git a/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts b/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts index fd3af0b0670cb..70aef7a04e087 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserActionTypes } from '../../../common/api'; +import type { UserActionTypes } from '../../../common/api'; import { CreateCaseUserActionBuilder } from './builders/create_case'; import { TitleUserActionBuilder } from './builders/title'; import { CommentUserActionBuilder } from './builders/comment'; @@ -16,10 +16,10 @@ import { StatusUserActionBuilder } from './builders/status'; import { TagsUserActionBuilder } from './builders/tags'; import { SettingsUserActionBuilder } from './builders/settings'; import { DeleteCaseUserActionBuilder } from './builders/delete_case'; -import { UserActionBuilder } from './abstract_builder'; +import type { UserActionBuilder } from './abstract_builder'; import { SeverityUserActionBuilder } from './builders/severity'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; -import { BuilderDeps } from './types'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { BuilderDeps } from './types'; import { AssigneesUserActionBuilder } from './builders/assignees'; const builderMap = { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/assignees.ts b/x-pack/plugins/cases/server/services/user_actions/builders/assignees.ts index 87e4a6ab19c76..554f70de71bcf 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/assignees.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/assignees.ts @@ -7,7 +7,7 @@ import { ActionTypes, Actions } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class AssigneesUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'assignees'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/comment.ts b/x-pack/plugins/cases/server/services/user_actions/builders/comment.ts index 97a6f87847f0f..a90a8b43b40ae 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/comment.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/comment.ts @@ -7,9 +7,10 @@ import { uniqBy } from 'lodash'; import { extractPersistableStateReferencesFromSO } from '../../../attachment_framework/so_references'; -import { ActionTypes, Actions, CommentUserAction } from '../../../../common/api'; +import type { CommentUserAction } from '../../../../common/api'; +import { ActionTypes, Actions } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; import { getAttachmentSOExtractor } from '../../so_references'; export class CommentUserActionBuilder extends UserActionBuilder { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/connector.ts b/x-pack/plugins/cases/server/services/user_actions/builders/connector.ts index 4168b68fbe278..0009105b964f0 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/connector.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/connector.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class ConnectorUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'connector'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts b/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts index 9261746d00cc0..6d83e9acb6383 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/create_case.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes, CaseStatuses } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class CreateCaseUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'create_case'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/delete_case.ts b/x-pack/plugins/cases/server/services/user_actions/builders/delete_case.ts index fd50ad63753cb..2200fcc0af08b 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/delete_case.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/delete_case.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class DeleteCaseUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'delete_case'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/description.ts b/x-pack/plugins/cases/server/services/user_actions/builders/description.ts index da263f7c7509e..95e506066ca6e 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/description.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/description.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class DescriptionUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'description'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/pushed.ts b/x-pack/plugins/cases/server/services/user_actions/builders/pushed.ts index b067df7b14a41..75a53a79de907 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/pushed.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/pushed.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class PushedUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'pushed'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/settings.ts b/x-pack/plugins/cases/server/services/user_actions/builders/settings.ts index e8b499465bb6c..d70f099539d65 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/settings.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/settings.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class SettingsUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'settings'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts b/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts index 4abd5856972b4..480fc6ffc5014 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class SeverityUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'severity'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/status.ts b/x-pack/plugins/cases/server/services/user_actions/builders/status.ts index 7c1f1b731bf76..1b3eaa9455d6b 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/status.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/status.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class StatusUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'status'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/tags.ts b/x-pack/plugins/cases/server/services/user_actions/builders/tags.ts index 1fecfa2c2786f..053c7d3fa91de 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/tags.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/tags.ts @@ -7,7 +7,7 @@ import { ActionTypes, Actions } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { UserActionParameters, BuilderReturnValue } from '../types'; +import type { UserActionParameters, BuilderReturnValue } from '../types'; export class TagsUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'tags'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/title.ts b/x-pack/plugins/cases/server/services/user_actions/builders/title.ts index 21b9cc86357c2..3d5251d84b629 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builders/title.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builders/title.ts @@ -7,7 +7,7 @@ import { Actions, ActionTypes } from '../../../../common/api'; import { UserActionBuilder } from '../abstract_builder'; -import { BuilderReturnValue, UserActionParameters } from '../types'; +import type { BuilderReturnValue, UserActionParameters } from '../types'; export class TitleUserActionBuilder extends UserActionBuilder { build(args: UserActionParameters<'title'>): BuilderReturnValue { diff --git a/x-pack/plugins/cases/server/services/user_actions/index.test.ts b/x-pack/plugins/cases/server/services/user_actions/index.test.ts index 151c8a6d40ed0..732b4e0c924f3 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.test.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.test.ts @@ -8,7 +8,7 @@ import { get, omit } from 'lodash'; import { loggerMock } from '@kbn/logging-mocks'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { +import type { SavedObject, SavedObjectReference, SavedObjectsFindResponse, @@ -16,16 +16,13 @@ import { SavedObjectsUpdateResponse, } from '@kbn/core/server'; import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; -import { - Actions, - ActionTypes, +import type { CaseAttributes, - CaseSeverity, - CaseStatuses, CaseUserActionAttributes, ConnectorUserAction, UserAction, } from '../../../common/api'; +import { Actions, ActionTypes, CaseSeverity, CaseStatuses } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, @@ -59,7 +56,7 @@ import { updatedTagsCases, } from './mocks'; import { CaseUserActionService, transformFindResponseToExternalModel } from '.'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; import { externalReferenceAttachmentSO, getPersistableStateAttachmentTypeRegistry, diff --git a/x-pack/plugins/cases/server/services/user_actions/index.ts b/x-pack/plugins/cases/server/services/user_actions/index.ts index 27ff69240e0ca..c27c313faaae7 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.ts @@ -7,7 +7,7 @@ import { get, isEmpty } from 'lodash'; -import { +import type { Logger, SavedObject, SavedObjectReference, @@ -17,7 +17,7 @@ import { } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { KueryNode } from '@kbn/es-query'; +import type { KueryNode } from '@kbn/es-query'; import { isCommentRequestTypePersistableState } from '../../../common/utils/attachments'; import { isConnectorUserAction, @@ -26,10 +26,8 @@ import { isCreateCaseUserAction, isCommentUserAction, } from '../../../common/utils/user_actions'; -import { +import type { ActionOperationValues, - Actions, - ActionTypes, ActionTypeValues, CaseAttributes, CaseUserActionAttributes, @@ -38,16 +36,16 @@ import { CaseUserProfile, CaseAssignees, CommentRequest, - NONE_CONNECTOR_ID, User, } from '../../../common/api'; +import { Actions, ActionTypes, NONE_CONNECTOR_ID } from '../../../common/api'; import { CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, MAX_DOCS_PER_PAGE, CASE_COMMENT_SAVED_OBJECT, } from '../../../common/constants'; -import { ClientArgs } from '..'; +import type { ClientArgs } from '..'; import { CASE_REF_NAME, COMMENT_REF_NAME, @@ -57,7 +55,7 @@ import { } from '../../common/constants'; import { findConnectorIdReference } from '../transform'; import { buildFilter, combineFilters, arraysDifference } from '../../client/utils'; -import { +import type { BuilderParameters, BuilderReturnValue, CommonArguments, @@ -66,9 +64,9 @@ import { } from './types'; import { BuilderFactory } from './builder_factory'; import { defaultSortField, isCommentRequestTypeExternalReferenceSO } from '../../common/utils'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; import { injectPersistableReferencesToSO } from '../../attachment_framework/so_references'; -import { IndexRefresh } from '../types'; +import type { IndexRefresh } from '../types'; import { isAssigneesArray, isStringArray } from './type_guards'; interface GetCaseUserActionArgs extends ClientArgs { diff --git a/x-pack/plugins/cases/server/services/user_actions/mocks.ts b/x-pack/plugins/cases/server/services/user_actions/mocks.ts index 80f2979716ca2..b7453d02f9524 100644 --- a/x-pack/plugins/cases/server/services/user_actions/mocks.ts +++ b/x-pack/plugins/cases/server/services/user_actions/mocks.ts @@ -7,13 +7,8 @@ import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; -import { - CasePostRequest, - CaseSeverity, - CaseStatuses, - CommentType, - ConnectorTypes, -} from '../../../common/api'; +import type { CasePostRequest } from '../../../common/api'; +import { CaseSeverity, CaseStatuses, CommentType, ConnectorTypes } from '../../../common/api'; import { createCaseSavedObjectResponse } from '../test_utils'; import { transformSavedObjectToExternalModel } from '../cases/transform'; diff --git a/x-pack/plugins/cases/server/services/user_actions/type_guards.ts b/x-pack/plugins/cases/server/services/user_actions/type_guards.ts index d1afd1b91c072..ee72239e55bce 100644 --- a/x-pack/plugins/cases/server/services/user_actions/type_guards.ts +++ b/x-pack/plugins/cases/server/services/user_actions/type_guards.ts @@ -6,7 +6,8 @@ */ import { isString } from 'lodash'; -import { CaseAssignees, CaseAssigneesRt } from '../../../common/api/cases/assignee'; +import type { CaseAssignees } from '../../../common/api/cases/assignee'; +import { CaseAssigneesRt } from '../../../common/api/cases/assignee'; export const isStringArray = (value: unknown): value is string[] => { return Array.isArray(value) && value.every((val) => isString(val)); diff --git a/x-pack/plugins/cases/server/services/user_actions/types.ts b/x-pack/plugins/cases/server/services/user_actions/types.ts index 667811b2b5317..153c09704aaa7 100644 --- a/x-pack/plugins/cases/server/services/user_actions/types.ts +++ b/x-pack/plugins/cases/server/services/user_actions/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectReference } from '@kbn/core/server'; -import { CaseAssignees } from '../../../common/api/cases/assignee'; -import { +import type { SavedObjectReference } from '@kbn/core/server'; +import type { CaseAssignees } from '../../../common/api/cases/assignee'; +import type { CasePostRequest, CaseSettings, CaseSeverity, @@ -19,7 +19,7 @@ import { UserAction, UserActionTypes, } from '../../../common/api'; -import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; export interface BuilderParameters { title: { diff --git a/x-pack/plugins/cases/server/services/user_profiles/index.ts b/x-pack/plugins/cases/server/services/user_profiles/index.ts index fb894fd82c34d..937e7449f89c7 100644 --- a/x-pack/plugins/cases/server/services/user_profiles/index.ts +++ b/x-pack/plugins/cases/server/services/user_profiles/index.ts @@ -10,12 +10,12 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; -import { KibanaRequest, Logger } from '@kbn/core/server'; -import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { KibanaRequest, Logger } from '@kbn/core/server'; +import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { UserProfile } from '@kbn/security-plugin/common'; -import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; -import { LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { excess, SuggestUserProfilesRequestRt, throwErrors } from '../../../common/api'; import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; diff --git a/x-pack/plugins/cases/server/telemetry/collect_telemetry_data.ts b/x-pack/plugins/cases/server/telemetry/collect_telemetry_data.ts index d62e33083b610..c3a595870c9ec 100644 --- a/x-pack/plugins/cases/server/telemetry/collect_telemetry_data.ts +++ b/x-pack/plugins/cases/server/telemetry/collect_telemetry_data.ts @@ -12,7 +12,7 @@ import { getConfigurationTelemetryData } from './queries/configuration'; import { getConnectorsTelemetryData } from './queries/connectors'; import { getPushedTelemetryData } from './queries/pushes'; import { getUserActionsTelemetryData } from './queries/user_actions'; -import { CasesTelemetry, CollectTelemetryDataParams } from './types'; +import type { CasesTelemetry, CollectTelemetryDataParams } from './types'; export const collectTelemetryData = async ({ savedObjectsClient, diff --git a/x-pack/plugins/cases/server/telemetry/index.ts b/x-pack/plugins/cases/server/telemetry/index.ts index fdba46d01240f..6cd796eca2c18 100644 --- a/x-pack/plugins/cases/server/telemetry/index.ts +++ b/x-pack/plugins/cases/server/telemetry/index.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { +import type { CoreSetup, ISavedObjectsRepository, Logger, PluginInitializerContext, - SavedObjectsErrorHelpers, } from '@kbn/core/server'; -import { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import { SavedObjectsErrorHelpers } from '@kbn/core/server'; +import type { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { collectTelemetryData } from './collect_telemetry_data'; import { CASE_TELEMETRY_SAVED_OBJECT, @@ -21,7 +21,7 @@ import { CASE_TELEMETRY_SAVED_OBJECT_ID, SAVED_OBJECT_TYPES, } from '../../common/constants'; -import { CasesTelemetry } from './types'; +import type { CasesTelemetry } from './types'; import { casesSchema } from './schema'; export { scheduleCasesTelemetryTask } from './schedule_telemetry_task'; diff --git a/x-pack/plugins/cases/server/telemetry/queries/alerts.ts b/x-pack/plugins/cases/server/telemetry/queries/alerts.ts index 8d7d67926a44b..96aaec211acb8 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/alerts.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/alerts.ts @@ -6,7 +6,7 @@ */ import { CASE_COMMENT_SAVED_OBJECT } from '../../../common/constants'; -import { CasesTelemetry, CollectTelemetryDataParams } from '../types'; +import type { CasesTelemetry, CollectTelemetryDataParams } from '../types'; import { getCountsAndMaxData, getOnlyAlertsCommentsFilter } from './utils'; export const getAlertsTelemetryData = async ({ diff --git a/x-pack/plugins/cases/server/telemetry/queries/cases.test.ts b/x-pack/plugins/cases/server/telemetry/queries/cases.test.ts index 2a6aaddf8f5db..73215ed35966a 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/cases.test.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/cases.test.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; import { savedObjectsRepositoryMock, loggingSystemMock } from '@kbn/core/server/mocks'; -import { CaseAggregationResult } from '../types'; +import type { CaseAggregationResult } from '../types'; import { getCasesTelemetryData } from './cases'; describe('getCasesTelemetryData', () => { diff --git a/x-pack/plugins/cases/server/telemetry/queries/cases.ts b/x-pack/plugins/cases/server/telemetry/queries/cases.ts index 3969ed77e5a17..e4e50dc7ad157 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/cases.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/cases.ts @@ -10,9 +10,9 @@ import { CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, } from '../../../common/constants'; -import { ESCaseAttributes } from '../../services/cases/types'; +import type { ESCaseAttributes } from '../../services/cases/types'; import { OWNERS } from '../constants'; -import { +import type { CollectTelemetryDataParams, Buckets, CasesTelemetry, diff --git a/x-pack/plugins/cases/server/telemetry/queries/comments.ts b/x-pack/plugins/cases/server/telemetry/queries/comments.ts index f57f83ead5860..f14c458ad03e4 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/comments.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/comments.ts @@ -7,7 +7,7 @@ import { CASE_COMMENT_SAVED_OBJECT } from '../../../common/constants'; import { buildFilter } from '../../client/utils'; -import { CasesTelemetry, CollectTelemetryDataParams } from '../types'; +import type { CasesTelemetry, CollectTelemetryDataParams } from '../types'; import { getCountsAndMaxData } from './utils'; export const getUserCommentsTelemetryData = async ({ diff --git a/x-pack/plugins/cases/server/telemetry/queries/configuration.ts b/x-pack/plugins/cases/server/telemetry/queries/configuration.ts index 35064ce95ee99..9a5b2bfe97f6a 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/configuration.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/configuration.ts @@ -6,7 +6,7 @@ */ import { CASE_CONFIGURE_SAVED_OBJECT } from '../../../common/constants'; -import { Buckets, CasesTelemetry, CollectTelemetryDataParams } from '../types'; +import type { Buckets, CasesTelemetry, CollectTelemetryDataParams } from '../types'; import { findValueInBuckets } from './utils'; export const getConfigurationTelemetryData = async ({ diff --git a/x-pack/plugins/cases/server/telemetry/queries/connectors.ts b/x-pack/plugins/cases/server/telemetry/queries/connectors.ts index efafbfb09feb9..8275ac86b729d 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/connectors.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/connectors.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; -import { KueryNode } from '@kbn/es-query'; -import { SavedObjectsFindResponse } from '@kbn/core/server'; +import type { AggregationsAggregationContainer } from '@elastic/elasticsearch/lib/api/types'; +import type { KueryNode } from '@kbn/es-query'; +import type { SavedObjectsFindResponse } from '@kbn/core/server'; import { CASE_USER_ACTION_SAVED_OBJECT } from '../../../common/constants'; import { buildFilter } from '../../client/utils'; -import { +import type { CasesTelemetry, CollectTelemetryDataParams, MaxBucketOnCaseAggregation, diff --git a/x-pack/plugins/cases/server/telemetry/queries/pushes.ts b/x-pack/plugins/cases/server/telemetry/queries/pushes.ts index 552b4ce83c8cb..0462a7ff0ef13 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/pushes.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/pushes.ts @@ -7,7 +7,11 @@ import { CASE_USER_ACTION_SAVED_OBJECT } from '../../../common/constants'; import { buildFilter } from '../../client/utils'; -import { CasesTelemetry, CollectTelemetryDataParams, MaxBucketOnCaseAggregation } from '../types'; +import type { + CasesTelemetry, + CollectTelemetryDataParams, + MaxBucketOnCaseAggregation, +} from '../types'; import { getMaxBucketOnCaseAggregationQuery } from './utils'; export const getPushedTelemetryData = async ({ diff --git a/x-pack/plugins/cases/server/telemetry/queries/user_actions.ts b/x-pack/plugins/cases/server/telemetry/queries/user_actions.ts index baddf07946f93..2f0b239ff1775 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/user_actions.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/user_actions.ts @@ -6,7 +6,7 @@ */ import { CASE_USER_ACTION_SAVED_OBJECT } from '../../../common/constants'; -import { CasesTelemetry, CollectTelemetryDataParams } from '../types'; +import type { CasesTelemetry, CollectTelemetryDataParams } from '../types'; import { getCountsAndMaxData } from './utils'; export const getUserActionsTelemetryData = async ({ diff --git a/x-pack/plugins/cases/server/telemetry/queries/utils.test.ts b/x-pack/plugins/cases/server/telemetry/queries/utils.test.ts index 3b1bd17b28cdf..e466ba597108a 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/utils.test.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/utils.test.ts @@ -6,7 +6,7 @@ */ import { savedObjectsRepositoryMock } from '@kbn/core/server/mocks'; -import { CaseAggregationResult } from '../types'; +import type { CaseAggregationResult } from '../types'; import { findValueInBuckets, getAggregationsBuckets, diff --git a/x-pack/plugins/cases/server/telemetry/queries/utils.ts b/x-pack/plugins/cases/server/telemetry/queries/utils.ts index dd542b5f65229..82bdef3ebe825 100644 --- a/x-pack/plugins/cases/server/telemetry/queries/utils.ts +++ b/x-pack/plugins/cases/server/telemetry/queries/utils.ts @@ -6,14 +6,14 @@ */ import { get } from 'lodash'; -import { KueryNode } from '@kbn/es-query'; -import { ISavedObjectsRepository } from '@kbn/core/server'; +import type { KueryNode } from '@kbn/es-query'; +import type { ISavedObjectsRepository } from '@kbn/core/server'; import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT, CASE_USER_ACTION_SAVED_OBJECT, } from '../../../common/constants'; -import { +import type { CaseAggregationResult, Buckets, CasesTelemetry, @@ -21,7 +21,7 @@ import { SolutionTelemetry, } from '../types'; import { buildFilter } from '../../client/utils'; -import { OWNERS } from '../constants'; +import type { OWNERS } from '../constants'; export const getCountsAggregationQuery = (savedObjectType: string) => ({ counts: { diff --git a/x-pack/plugins/cases/server/telemetry/schedule_telemetry_task.ts b/x-pack/plugins/cases/server/telemetry/schedule_telemetry_task.ts index d33e68597f107..eae5a8a84ce87 100644 --- a/x-pack/plugins/cases/server/telemetry/schedule_telemetry_task.ts +++ b/x-pack/plugins/cases/server/telemetry/schedule_telemetry_task.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { Logger } from '@kbn/core/server'; -import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; +import type { Logger } from '@kbn/core/server'; +import type { TaskManagerStartContract } from '@kbn/task-manager-plugin/server'; import { CASES_TELEMETRY_TASK_NAME } from '../../common/constants'; const MINUTES_ON_HALF_DAY = 60 * 12; diff --git a/x-pack/plugins/cases/server/telemetry/schema.ts b/x-pack/plugins/cases/server/telemetry/schema.ts index fa04fc7c6651d..1f51ca134b577 100644 --- a/x-pack/plugins/cases/server/telemetry/schema.ts +++ b/x-pack/plugins/cases/server/telemetry/schema.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { +import type { CasesTelemetrySchema, TypeLong, CountSchema, diff --git a/x-pack/plugins/cases/server/telemetry/types.ts b/x-pack/plugins/cases/server/telemetry/types.ts index 2c8e848b3854f..095b967d1addf 100644 --- a/x-pack/plugins/cases/server/telemetry/types.ts +++ b/x-pack/plugins/cases/server/telemetry/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { ISavedObjectsRepository, Logger } from '@kbn/core/server'; -import { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server'; -import { OWNERS } from './constants'; +import type { ISavedObjectsRepository, Logger } from '@kbn/core/server'; +import type { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server'; +import type { OWNERS } from './constants'; export interface Buckets { buckets: Array<{ diff --git a/x-pack/plugins/cases/server/types.ts b/x-pack/plugins/cases/server/types.ts index 3fe3c0cd72d90..3c92a9a16cdbc 100644 --- a/x-pack/plugins/cases/server/types.ts +++ b/x-pack/plugins/cases/server/types.ts @@ -6,14 +6,14 @@ */ import type { IRouter, CustomRequestHandlerContext, KibanaRequest } from '@kbn/core/server'; -import { +import type { ActionTypeConfig, ActionTypeSecrets, ActionTypeParams, ActionType, } from '@kbn/actions-plugin/server/types'; -import { CasesClient } from './client'; -import { AttachmentFramework } from './attachment_framework/types'; +import type { CasesClient } from './client'; +import type { AttachmentFramework } from './attachment_framework/types'; export interface CaseRequestContext { getCasesClient: () => Promise; diff --git a/x-pack/plugins/cloud/README.md b/x-pack/plugins/cloud/README.md index 77f73a3eaea01..0b9a75de7e030 100644 --- a/x-pack/plugins/cloud/README.md +++ b/x-pack/plugins/cloud/README.md @@ -52,4 +52,14 @@ This is the path to the Cloud Account and Billing page. The value is already pre This value is the same as `baseUrl` on ESS but can be customized on ECE. -**Example:** `cloud.elastic.co` (on ESS) \ No newline at end of file +**Example:** `cloud.elastic.co` (on ESS) + +### `trial_end_date` + +The end date for the Elastic Cloud trial. Only available on Elastic Cloud. + +**Example:** `2020-10-14T10:40:22Z` + +### `is_elastic_staff_owned` + +`true` if the deployment is owned by an Elastician. Only available on Elastic Cloud. \ No newline at end of file diff --git a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.test.ts b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.test.ts index a6dc1f59b00e3..4793bb1ac6af9 100644 --- a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.test.ts +++ b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.test.ts @@ -6,7 +6,7 @@ */ import { firstValueFrom } from 'rxjs'; -import { registerCloudDeploymentIdAnalyticsContext } from './register_cloud_deployment_id_analytics_context'; +import { registerCloudDeploymentMetadataAnalyticsContext } from './register_cloud_deployment_id_analytics_context'; describe('registerCloudDeploymentIdAnalyticsContext', () => { let analytics: { registerContextProvider: jest.Mock }; @@ -17,14 +17,16 @@ describe('registerCloudDeploymentIdAnalyticsContext', () => { }); test('it does not register the context provider if cloudId not provided', () => { - registerCloudDeploymentIdAnalyticsContext(analytics); + registerCloudDeploymentMetadataAnalyticsContext(analytics, {}); expect(analytics.registerContextProvider).not.toHaveBeenCalled(); }); test('it registers the context provider and emits the cloudId', async () => { - registerCloudDeploymentIdAnalyticsContext(analytics, 'cloud_id'); + registerCloudDeploymentMetadataAnalyticsContext(analytics, { id: 'cloud_id' }); expect(analytics.registerContextProvider).toHaveBeenCalledTimes(1); const [{ context$ }] = analytics.registerContextProvider.mock.calls[0]; - await expect(firstValueFrom(context$)).resolves.toEqual({ cloudId: 'cloud_id' }); + await expect(firstValueFrom(context$)).resolves.toEqual({ + cloudId: 'cloud_id', + }); }); }); diff --git a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts index e8bdc6b37b50c..68130cdcda799 100644 --- a/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts +++ b/x-pack/plugins/cloud/common/register_cloud_deployment_id_analytics_context.ts @@ -8,21 +8,44 @@ import type { AnalyticsClient } from '@kbn/analytics-client'; import { of } from 'rxjs'; -export function registerCloudDeploymentIdAnalyticsContext( +export interface CloudDeploymentMetadata { + id?: string; + trial_end_date?: string; + is_elastic_staff_owned?: boolean; +} + +export function registerCloudDeploymentMetadataAnalyticsContext( analytics: Pick, - cloudId?: string + cloudMetadata: CloudDeploymentMetadata ) { - if (!cloudId) { + if (!cloudMetadata.id) { return; } + const { + id: cloudId, + trial_end_date: cloudTrialEndDate, + is_elastic_staff_owned: cloudIsElasticStaffOwned, + } = cloudMetadata; + analytics.registerContextProvider({ - name: 'Cloud Deployment ID', - context$: of({ cloudId }), + name: 'Cloud Deployment Metadata', + context$: of({ cloudId, cloudTrialEndDate, cloudIsElasticStaffOwned }), schema: { cloudId: { type: 'keyword', _meta: { description: 'The Cloud Deployment ID' }, }, + cloudTrialEndDate: { + type: 'date', + _meta: { description: 'When the Elastic Cloud trial ends/ended', optional: true }, + }, + cloudIsElasticStaffOwned: { + type: 'boolean', + _meta: { + description: '`true` if the owner of the deployment is an Elastician', + optional: true, + }, + }, }, }); } diff --git a/x-pack/plugins/cloud/public/mocks.tsx b/x-pack/plugins/cloud/public/mocks.tsx index 608e826657b73..fb1b66adcec98 100644 --- a/x-pack/plugins/cloud/public/mocks.tsx +++ b/x-pack/plugins/cloud/public/mocks.tsx @@ -18,6 +18,8 @@ function createSetupMock() { deploymentUrl: 'deployment-url', profileUrl: 'profile-url', organizationUrl: 'organization-url', + isElasticStaffOwned: true, + trialEndDate: new Date('2020-10-01T14:13:12Z'), registerCloudService: jest.fn(), }; } diff --git a/x-pack/plugins/cloud/public/plugin.tsx b/x-pack/plugins/cloud/public/plugin.tsx index f50f41f3c79cd..ded7924b50631 100644 --- a/x-pack/plugins/cloud/public/plugin.tsx +++ b/x-pack/plugins/cloud/public/plugin.tsx @@ -8,7 +8,7 @@ import React, { FC } from 'react'; import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; -import { registerCloudDeploymentIdAnalyticsContext } from '../common/register_cloud_deployment_id_analytics_context'; +import { registerCloudDeploymentMetadataAnalyticsContext } from '../common/register_cloud_deployment_id_analytics_context'; import { getIsCloudEnabled } from '../common/is_cloud_enabled'; import { ELASTIC_SUPPORT_LINK, CLOUD_SNAPSHOTS_PATH } from '../common/constants'; import { getFullCloudUrl } from './utils'; @@ -20,11 +20,8 @@ export interface CloudConfigType { profile_url?: string; deployment_url?: string; organization_url?: string; - full_story: { - enabled: boolean; - org_id?: string; - eventTypesAllowlist?: string[]; - }; + trial_end_date?: string; + is_elastic_staff_owned?: boolean; } export interface CloudStart { @@ -55,14 +52,50 @@ export interface CloudStart { } export interface CloudSetup { + /** + * Cloud ID. Undefined if not running on Cloud. + */ cloudId?: string; + /** + * This value is the same as `baseUrl` on ESS but can be customized on ECE. + */ cname?: string; + /** + * This is the URL of the Cloud interface. + */ baseUrl?: string; + /** + * The full URL to the deployment management page on Elastic Cloud. Undefined if not running on Cloud. + */ deploymentUrl?: string; + /** + * The full URL to the user profile page on Elastic Cloud. Undefined if not running on Cloud. + */ profileUrl?: string; + /** + * The full URL to the organization management page on Elastic Cloud. Undefined if not running on Cloud. + */ organizationUrl?: string; + /** + * This is the path to the Snapshots page for the deployment to which the Kibana instance belongs. The value is already prepended with `deploymentUrl`. + */ snapshotsUrl?: string; + /** + * `true` when Kibana is running on Elastic Cloud. + */ isCloudEnabled: boolean; + /** + * When the Cloud Trial ends/ended for the organization that owns this deployment. Only available when running on Elastic Cloud. + */ + trialEndDate?: Date; + /** + * `true` if the Elastic Cloud organization that owns this deployment is owned by an Elastician. Only available when running on Elastic Cloud. + */ + isElasticStaffOwned?: boolean; + /** + * Registers CloudServiceProviders so start's `CloudContextProvider` hooks them. + * @param contextProvider The React component from the Service Provider. + */ registerCloudService: (contextProvider: FC) => void; } @@ -84,15 +117,23 @@ export class CloudPlugin implements Plugin { } public setup(core: CoreSetup): CloudSetup { - registerCloudDeploymentIdAnalyticsContext(core.analytics, this.config.id); + registerCloudDeploymentMetadataAnalyticsContext(core.analytics, this.config); - const { id, cname, base_url: baseUrl } = this.config; + const { + id, + cname, + base_url: baseUrl, + trial_end_date: trialEndDate, + is_elastic_staff_owned: isElasticStaffOwned, + } = this.config; return { cloudId: id, cname, baseUrl, ...this.getCloudUrls(), + trialEndDate: trialEndDate ? new Date(trialEndDate) : undefined, + isElasticStaffOwned, isCloudEnabled: this.isCloudEnabled, registerCloudService: (contextProvider) => { this.contextProviders.push(contextProvider); diff --git a/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.test.ts b/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.test.ts index f9fdef5319d59..612b75e5d68d3 100644 --- a/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.test.ts +++ b/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.test.ts @@ -5,31 +5,51 @@ * 2.0. */ +import { + createCollectorFetchContextMock, + usageCollectionPluginMock, +} from '@kbn/usage-collection-plugin/server/mocks'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { createCloudUsageCollector } from './cloud_usage_collector'; -import { createCollectorFetchContextMock } from '@kbn/usage-collection-plugin/server/mocks'; +import { CollectorFetchContext } from '@kbn/usage-collection-plugin/server'; -const mockUsageCollection = () => ({ - makeUsageCollector: jest.fn().mockImplementation((args: any) => ({ ...args })), -}); +describe('createCloudUsageCollector', () => { + let usageCollection: UsageCollectionSetup; + let collectorFetchContext: jest.Mocked; -const getMockConfigs = (isCloudEnabled: boolean) => ({ isCloudEnabled }); + beforeEach(() => { + usageCollection = usageCollectionPluginMock.createSetupContract(); + collectorFetchContext = createCollectorFetchContextMock(); + }); -describe('createCloudUsageCollector', () => { it('calls `makeUsageCollector`', () => { - const mockConfigs = getMockConfigs(false); - const usageCollection = mockUsageCollection(); - createCloudUsageCollector(usageCollection as any, mockConfigs); + createCloudUsageCollector(usageCollection, { isCloudEnabled: false }); expect(usageCollection.makeUsageCollector).toBeCalledTimes(1); }); describe('Fetched Usage data', () => { it('return isCloudEnabled boolean', async () => { - const mockConfigs = getMockConfigs(true); - const usageCollection = mockUsageCollection() as any; - const collector = createCloudUsageCollector(usageCollection, mockConfigs); - const collectorFetchContext = createCollectorFetchContextMock(); + const collector = createCloudUsageCollector(usageCollection, { isCloudEnabled: true }); + + expect(await collector.fetch(collectorFetchContext)).toStrictEqual({ + isCloudEnabled: true, + isElasticStaffOwned: undefined, + trialEndDate: undefined, + }); + }); + + it('return inTrial boolean if trialEndDateIsProvided', async () => { + const collector = createCloudUsageCollector(usageCollection, { + isCloudEnabled: true, + trialEndDate: '2020-10-01T14:30:16Z', + }); - expect((await collector.fetch(collectorFetchContext)).isCloudEnabled).toBe(true); // Adding the await because the fetch can be a Promise or a synchronous method and TS complains in the test if not awaited + expect(await collector.fetch(collectorFetchContext)).toStrictEqual({ + isCloudEnabled: true, + isElasticStaffOwned: undefined, + trialEndDate: '2020-10-01T14:30:16Z', + inTrial: false, + }); }); }); }); diff --git a/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.ts b/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.ts index 28f6e8c94d0b8..147f61a57312b 100644 --- a/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.ts +++ b/x-pack/plugins/cloud/server/collectors/cloud_usage_collector.ts @@ -9,23 +9,35 @@ import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; interface Config { isCloudEnabled: boolean; + trialEndDate?: string; + isElasticStaffOwned?: boolean; } interface CloudUsage { isCloudEnabled: boolean; + trialEndDate?: string; + inTrial?: boolean; + isElasticStaffOwned?: boolean; } export function createCloudUsageCollector(usageCollection: UsageCollectionSetup, config: Config) { - const { isCloudEnabled } = config; + const { isCloudEnabled, trialEndDate, isElasticStaffOwned } = config; + const trialEndDateMs = trialEndDate ? new Date(trialEndDate).getTime() : undefined; return usageCollection.makeUsageCollector({ type: 'cloud', isReady: () => true, schema: { isCloudEnabled: { type: 'boolean' }, + trialEndDate: { type: 'date' }, + inTrial: { type: 'boolean' }, + isElasticStaffOwned: { type: 'boolean' }, }, fetch: () => { return { isCloudEnabled, + isElasticStaffOwned, + trialEndDate, + ...(trialEndDateMs ? { inTrial: Date.now() <= trialEndDateMs } : {}), }; }, }); diff --git a/x-pack/plugins/cloud/server/config.ts b/x-pack/plugins/cloud/server/config.ts index 512542c756798..028298c2da331 100644 --- a/x-pack/plugins/cloud/server/config.ts +++ b/x-pack/plugins/cloud/server/config.ts @@ -26,6 +26,8 @@ const configSchema = schema.object({ id: schema.maybe(schema.string()), organization_url: schema.maybe(schema.string()), profile_url: schema.maybe(schema.string()), + trial_end_date: schema.maybe(schema.string()), + is_elastic_staff_owned: schema.maybe(schema.boolean()), }); export type CloudConfigType = TypeOf; @@ -38,6 +40,8 @@ export const config: PluginConfigDescriptor = { id: true, organization_url: true, profile_url: true, + trial_end_date: true, + is_elastic_staff_owned: true, }, schema: configSchema, }; diff --git a/x-pack/plugins/cloud/server/mocks.ts b/x-pack/plugins/cloud/server/mocks.ts index 557e64edf6cc1..ad64768951450 100644 --- a/x-pack/plugins/cloud/server/mocks.ts +++ b/x-pack/plugins/cloud/server/mocks.ts @@ -13,6 +13,8 @@ function createSetupMock(): jest.Mocked { instanceSizeMb: 1234, deploymentId: 'deployment-id', isCloudEnabled: true, + isElasticStaffOwned: true, + trialEndDate: new Date('2020-10-01T14:13:12Z'), apm: { url: undefined, secretToken: undefined, diff --git a/x-pack/plugins/cloud/server/plugin.ts b/x-pack/plugins/cloud/server/plugin.ts index 9cf1a308800a0..4e54c2b9b7f40 100644 --- a/x-pack/plugins/cloud/server/plugin.ts +++ b/x-pack/plugins/cloud/server/plugin.ts @@ -7,7 +7,7 @@ import type { CoreSetup, Plugin, PluginInitializerContext } from '@kbn/core/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { registerCloudDeploymentIdAnalyticsContext } from '../common/register_cloud_deployment_id_analytics_context'; +import { registerCloudDeploymentMetadataAnalyticsContext } from '../common/register_cloud_deployment_id_analytics_context'; import type { CloudConfigType } from './config'; import { registerCloudUsageCollector } from './collectors'; import { getIsCloudEnabled } from '../common/is_cloud_enabled'; @@ -18,11 +18,37 @@ interface PluginsSetup { usageCollection?: UsageCollectionSetup; } +/** + * Setup contract + */ export interface CloudSetup { + /** + * The deployment's Cloud ID. Only available when running on Elastic Cloud. + */ cloudId?: string; + /** + * The deployment's ID. Only available when running on Elastic Cloud. + */ deploymentId?: string; + /** + * `true` when running on Elastic Cloud. + */ isCloudEnabled: boolean; + /** + * The size of the instance in which Kibana is running. Only available when running on Elastic Cloud. + */ instanceSizeMb?: number; + /** + * When the Cloud Trial ends/ended for the organization that owns this deployment. Only available when running on Elastic Cloud. + */ + trialEndDate?: Date; + /** + * `true` if the Elastic Cloud organization that owns this deployment is owned by an Elastician. Only available when running on Elastic Cloud. + */ + isElasticStaffOwned?: boolean; + /** + * APM configuration keys. + */ apm: { url?: string; secretToken?: string; @@ -38,14 +64,20 @@ export class CloudPlugin implements Plugin { public setup(core: CoreSetup, { usageCollection }: PluginsSetup): CloudSetup { const isCloudEnabled = getIsCloudEnabled(this.config.id); - registerCloudDeploymentIdAnalyticsContext(core.analytics, this.config.id); - registerCloudUsageCollector(usageCollection, { isCloudEnabled }); + registerCloudDeploymentMetadataAnalyticsContext(core.analytics, this.config); + registerCloudUsageCollector(usageCollection, { + isCloudEnabled, + trialEndDate: this.config.trial_end_date, + isElasticStaffOwned: this.config.is_elastic_staff_owned, + }); return { cloudId: this.config.id, instanceSizeMb: readInstanceSizeMb(), deploymentId: parseDeploymentIdFromDeploymentUrl(this.config.deployment_url), isCloudEnabled, + trialEndDate: this.config.trial_end_date ? new Date(this.config.trial_end_date) : undefined, + isElasticStaffOwned: this.config.is_elastic_staff_owned, apm: { url: this.config.apm?.url, secretToken: this.config.apm?.secret_token, diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/index.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/index.ts new file mode 100644 index 0000000000000..74e2655e8302f --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { MetadataService } from './metadata_service'; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts new file mode 100644 index 0000000000000..8764eb434213e --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.test.ts @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import { fakeSchedulers } from 'rxjs-marbles/jest'; +import { firstValueFrom } from 'rxjs'; +import { MetadataService } from './metadata_service'; + +jest.mock('rxjs', () => { + const RxJs = jest.requireActual('rxjs'); + + return { + ...RxJs, + debounceTime: () => RxJs.identity, // Remove the delaying effect of debounceTime + }; +}); + +describe('MetadataService', () => { + jest.useFakeTimers(); + + let metadataService: MetadataService; + + beforeEach(() => { + metadataService = new MetadataService({ metadata_refresh_interval: moment.duration(1, 's') }); + }); + + afterEach(() => { + jest.clearAllTimers(); + jest.clearAllMocks(); + }); + + describe('setup', () => { + test('emits the initial metadata', async () => { + const initialMetadata = { userId: 'fake-user-id', kibanaVersion: 'version' }; + metadataService.setup(initialMetadata); + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual( + initialMetadata + ); + }); + + test( + 'emits in_trial when trial_end_date is provided', + fakeSchedulers(async (advance) => { + const initialMetadata = { + userId: 'fake-user-id', + kibanaVersion: 'version', + trial_end_date: new Date(0).toISOString(), + }; + metadataService.setup(initialMetadata); + + // Still equals initialMetadata + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual( + initialMetadata + ); + + // After scheduler kicks in... + advance(1); // The timer kicks in first on 0 (but let's give us 1ms so the trial is expired) + await new Promise((resolve) => process.nextTick(resolve)); // The timer triggers a promise, so we need to skip to the next tick + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual({ + ...initialMetadata, + in_trial: false, + }); + }) + ); + }); + + describe('start', () => { + const initialMetadata = { userId: 'fake-user-id', kibanaVersion: 'version' }; + beforeEach(() => { + metadataService.setup(initialMetadata); + }); + + test( + 'emits has_data after resolving the `hasUserDataView`', + fakeSchedulers(async (advance) => { + metadataService.start({ hasDataFetcher: async () => ({ has_data: true }) }); + + // Still equals initialMetadata + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual( + initialMetadata + ); + + // After scheduler kicks in... + advance(1); // The timer kicks in first on 0 (but let's give us 1ms so the trial is expired) + await new Promise((resolve) => process.nextTick(resolve)); // The timer triggers a promise, so we need to skip to the next tick + await expect(firstValueFrom(metadataService.userMetadata$)).resolves.toStrictEqual({ + ...initialMetadata, + has_data: true, + }); + }) + ); + }); +}); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.ts new file mode 100644 index 0000000000000..6691211b7b01c --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/common/metadata_service/metadata_service.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + BehaviorSubject, + debounceTime, + distinct, + exhaustMap, + filter, + type Observable, + shareReplay, + Subject, + takeUntil, + takeWhile, + timer, +} from 'rxjs'; +import { type Duration } from 'moment'; + +export interface MetadataServiceStartContract { + hasDataFetcher: () => Promise<{ has_data: boolean }>; +} + +export interface UserMetadata extends Record { + // Static values + userId: string; + kibanaVersion: string; + trial_end_date?: string; + is_elastic_staff_owned?: boolean; + // Dynamic/calculated values + in_trial?: boolean; + has_data?: boolean; +} + +export interface MetadataServiceConfig { + metadata_refresh_interval: Duration; +} + +export class MetadataService { + private readonly _userMetadata$ = new BehaviorSubject(undefined); + private readonly stop$ = new Subject(); + + constructor(private readonly config: MetadataServiceConfig) {} + + public setup(initialUserMetadata: UserMetadata) { + this._userMetadata$.next(initialUserMetadata); + + // Calculate `in_trial` based on the `trial_end_date`. + // Elastic Cloud allows customers to end their trials earlier or even extend it in some cases, but this is a good compromise for now. + const trialEndDate = initialUserMetadata.trial_end_date; + if (trialEndDate) { + this.scheduleUntil( + () => ({ in_trial: Date.now() <= new Date(trialEndDate).getTime() }), + // Stop recalculating in_trial when the user is no-longer in trial + (metadata) => metadata.in_trial === false + ); + } + } + + public get userMetadata$(): Observable { + return this._userMetadata$.pipe( + filter(Boolean), // Ensure we don't return undefined + debounceTime(100), // Swallows multiple emissions that may occur during bootstrap + distinct((meta) => [meta.in_trial, meta.has_data].join('-')), // Checks if any of the dynamic fields have changed + shareReplay(1) + ); + } + + public start({ hasDataFetcher }: MetadataServiceStartContract) { + // If no initial metadata (setup was not called) => it should not schedule any metadata extension + if (!this._userMetadata$.value) return; + + this.scheduleUntil( + async () => hasDataFetcher(), + // Stop checking the moment the user has any data + (metadata) => metadata.has_data === true + ); + } + + public stop() { + this.stop$.next(); + this._userMetadata$.complete(); + } + + /** + * Schedules a timer that calls `fn` to update the {@link UserMetadata} until `untilFn` returns true. + * @param fn Method to calculate the dynamic metadata. + * @param untilFn Method that returns true when the scheduler should stop calling fn (potentially because the dynamic value is not expected to change anymore). + * @private + */ + private scheduleUntil( + fn: () => Partial | Promise>, + untilFn: (value: UserMetadata) => boolean + ) { + timer(0, this.config.metadata_refresh_interval.asMilliseconds()) + .pipe( + takeUntil(this.stop$), + exhaustMap(async () => { + this._userMetadata$.next({ + ...this._userMetadata$.value!, // We are running the schedules after the initial user metadata is set + ...(await fn()), + }); + }), + takeWhile(() => { + return !untilFn(this._userMetadata$.value!); + }) + ) + .subscribe(); + } +} diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/kibana.json b/x-pack/plugins/cloud_integrations/cloud_experiments/kibana.json index 6bbb41f796f94..6dc3e8fe34c87 100755 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/kibana.json +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/kibana.json @@ -10,6 +10,6 @@ "server": true, "ui": true, "configPath": ["xpack", "cloud_integrations", "experiments"], - "requiredPlugins": ["cloud"], + "requiredPlugins": ["cloud", "dataViews"], "optionalPlugins": ["usageCollection"] } diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/index.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/index.ts new file mode 100644 index 0000000000000..ac961286b7043 --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { + LaunchDarklyClient, + type LaunchDarklyUserMetadata, + type LaunchDarklyClientConfig, +} from './launch_darkly_client'; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.mock.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.test.mock.ts similarity index 80% rename from x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.mock.ts rename to x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.test.mock.ts index d2bfb5b54213d..b6a43a7d0715b 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.mock.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.test.mock.ts @@ -9,16 +9,19 @@ import type { LDClient } from 'launchdarkly-js-client-sdk'; export function createLaunchDarklyClientMock(): jest.Mocked { return { + identify: jest.fn(), waitForInitialization: jest.fn(), variation: jest.fn(), track: jest.fn(), - identify: jest.fn(), flush: jest.fn(), } as unknown as jest.Mocked; // Using casting because we only use these APIs. No need to declare everything. } export const ldClientMock = createLaunchDarklyClientMock(); -jest.doMock('launchdarkly-js-client-sdk', () => ({ - initialize: () => ldClientMock, -})); +export const launchDarklyLibraryMock = { + initialize: jest.fn(), + basicLogger: jest.fn(), +}; + +jest.doMock('launchdarkly-js-client-sdk', () => launchDarklyLibraryMock); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.test.ts new file mode 100644 index 0000000000000..8f4b0d63c9947 --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ldClientMock, launchDarklyLibraryMock } from './launch_darkly_client.test.mock'; +import { LaunchDarklyClient, type LaunchDarklyClientConfig } from './launch_darkly_client'; + +describe('LaunchDarklyClient - browser', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const config: LaunchDarklyClientConfig = { + client_id: 'fake-client-id', + client_log_level: 'debug', + }; + + describe('Public APIs', () => { + let client: LaunchDarklyClient; + const testUserMetadata = { userId: 'fake-user-id', kibanaVersion: 'version' }; + + beforeEach(() => { + client = new LaunchDarklyClient(config, 'version'); + }); + + describe('updateUserMetadata', () => { + test("calls the client's initialize method with all the possible values", async () => { + expect(client).toHaveProperty('launchDarklyClient', undefined); + + launchDarklyLibraryMock.initialize.mockReturnValue(ldClientMock); + + const topFields = { + name: 'First Last', + firstName: 'First', + lastName: 'Last', + email: 'first.last@boring.co', + avatar: 'fake-blue-avatar', + ip: 'my-weird-ip', + country: 'distributed', + }; + + const extraFields = { + other_field: 'my other custom field', + kibanaVersion: 'version', + }; + + await client.updateUserMetadata({ userId: 'fake-user-id', ...topFields, ...extraFields }); + + expect(launchDarklyLibraryMock.initialize).toHaveBeenCalledWith( + 'fake-client-id', + { + key: 'fake-user-id', + ...topFields, + custom: extraFields, + }, + { + application: { id: 'kibana-browser', version: 'version' }, + logger: undefined, + } + ); + + expect(client).toHaveProperty('launchDarklyClient', ldClientMock); + }); + + test('sets a minimum amount of info', async () => { + expect(client).toHaveProperty('launchDarklyClient', undefined); + + await client.updateUserMetadata({ userId: 'fake-user-id', kibanaVersion: 'version' }); + + expect(launchDarklyLibraryMock.initialize).toHaveBeenCalledWith( + 'fake-client-id', + { + key: 'fake-user-id', + custom: { kibanaVersion: 'version' }, + }, + { + application: { id: 'kibana-browser', version: 'version' }, + logger: undefined, + } + ); + }); + + test('calls identify if an update comes after initializing the client', async () => { + expect(client).toHaveProperty('launchDarklyClient', undefined); + + launchDarklyLibraryMock.initialize.mockReturnValue(ldClientMock); + await client.updateUserMetadata({ userId: 'fake-user-id', kibanaVersion: 'version' }); + + expect(launchDarklyLibraryMock.initialize).toHaveBeenCalledWith( + 'fake-client-id', + { + key: 'fake-user-id', + custom: { kibanaVersion: 'version' }, + }, + { + application: { id: 'kibana-browser', version: 'version' }, + logger: undefined, + } + ); + expect(ldClientMock.identify).not.toHaveBeenCalled(); + + expect(client).toHaveProperty('launchDarklyClient', ldClientMock); + + // Update user metadata a 2nd time + await client.updateUserMetadata({ userId: 'fake-user-id', kibanaVersion: 'version' }); + expect(ldClientMock.identify).toHaveBeenCalledWith({ + key: 'fake-user-id', + custom: { kibanaVersion: 'version' }, + }); + }); + }); + + describe('getVariation', () => { + test('returns the default value if the user has not been defined', async () => { + await expect(client.getVariation('my-feature-flag', 123)).resolves.toStrictEqual(123); + expect(ldClientMock.variation).toHaveBeenCalledTimes(0); + }); + + test('calls the LaunchDarkly client when the user has been defined', async () => { + ldClientMock.variation.mockResolvedValue(1234); + await client.updateUserMetadata(testUserMetadata); + await expect(client.getVariation('my-feature-flag', 123)).resolves.toStrictEqual(1234); + expect(ldClientMock.variation).toHaveBeenCalledTimes(1); + expect(ldClientMock.variation).toHaveBeenCalledWith('my-feature-flag', 123); + }); + }); + + describe('reportMetric', () => { + test('does not call track if the user has not been defined', () => { + client.reportMetric('my-feature-flag', {}, 123); + expect(ldClientMock.track).toHaveBeenCalledTimes(0); + }); + + test('calls the LaunchDarkly client when the user has been defined', async () => { + await client.updateUserMetadata(testUserMetadata); + client.reportMetric('my-feature-flag', {}, 123); + expect(ldClientMock.track).toHaveBeenCalledTimes(1); + expect(ldClientMock.track).toHaveBeenCalledWith('my-feature-flag', {}, 123); + }); + }); + + describe('stop', () => { + test('flushes the events', async () => { + await client.updateUserMetadata(testUserMetadata); + + ldClientMock.flush.mockResolvedValue(); + expect(() => client.stop()).not.toThrow(); + expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the flush resolution + }); + + test('handles errors when flushing events', async () => { + await client.updateUserMetadata(testUserMetadata); + + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + const err = new Error('Something went terribly wrong'); + ldClientMock.flush.mockRejectedValue(err); + expect(() => client.stop()).not.toThrow(); + expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the flush resolution + expect(consoleWarnSpy).toHaveBeenCalledWith(err); + }); + }); + }); +}); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.ts new file mode 100644 index 0000000000000..f78286f0fa8ca --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/launch_darkly_client/launch_darkly_client.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { type LDClient, type LDUser, type LDLogLevel } from 'launchdarkly-js-client-sdk'; + +export interface LaunchDarklyClientConfig { + client_id: string; + client_log_level: LDLogLevel; +} + +export interface LaunchDarklyUserMetadata + extends Record { + userId: string; + // We are not collecting any of the above, but this is to match the LDUser first-level definition + name?: string; + firstName?: string; + lastName?: string; + email?: string; + avatar?: string; + ip?: string; + country?: string; +} + +export class LaunchDarklyClient { + private launchDarklyClient?: LDClient; + + constructor( + private readonly ldConfig: LaunchDarklyClientConfig, + private readonly kibanaVersion: string + ) {} + + public async updateUserMetadata(userMetadata: LaunchDarklyUserMetadata) { + const { userId, name, firstName, lastName, email, avatar, ip, country, ...custom } = + userMetadata; + const launchDarklyUser: LDUser = { + key: userId, + name, + firstName, + lastName, + email, + avatar, + ip, + country, + // This casting is needed because LDUser does not allow `Record` + custom: custom as Record, + }; + if (this.launchDarklyClient) { + await this.launchDarklyClient.identify(launchDarklyUser); + } else { + const { initialize, basicLogger } = await import('launchdarkly-js-client-sdk'); + this.launchDarklyClient = initialize(this.ldConfig.client_id, launchDarklyUser, { + application: { id: 'kibana-browser', version: this.kibanaVersion }, + logger: basicLogger({ level: this.ldConfig.client_log_level }), + }); + } + } + + public async getVariation(configKey: string, defaultValue: Data): Promise { + if (!this.launchDarklyClient) return defaultValue; // Skip any action if no LD User is defined + await this.launchDarklyClient.waitForInitialization(); + return await this.launchDarklyClient.variation(configKey, defaultValue); + } + + public reportMetric(metricName: string, meta?: unknown, value?: number): void { + if (!this.launchDarklyClient) return; // Skip any action if no LD User is defined + this.launchDarklyClient.track(metricName, meta, value); + } + + public stop() { + this.launchDarklyClient + ?.flush() + // eslint-disable-next-line no-console + .catch((err) => console.warn(err)); + } +} diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.ts index 3c6396d686796..9c1e3d25537fd 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.test.ts @@ -5,17 +5,30 @@ * 2.0. */ +import { duration } from 'moment'; import { coreMock } from '@kbn/core/public/mocks'; import { cloudMock } from '@kbn/cloud-plugin/public/mocks'; -import { ldClientMock } from './plugin.test.mock'; -import { CloudExperimentsPlugin } from './plugin'; +import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; +import { CloudExperimentsPluginStart } from '../common'; import { FEATURE_FLAG_NAMES } from '../common/constants'; +import { CloudExperimentsPlugin } from './plugin'; +import { LaunchDarklyClient } from './launch_darkly_client'; +import { MetadataService } from '../common/metadata_service'; +jest.mock('./launch_darkly_client'); + +function getLaunchDarklyClientInstanceMock() { + const launchDarklyClientInstanceMock = ( + LaunchDarklyClient as jest.MockedClass + ).mock.instances[0] as jest.Mocked; + + return launchDarklyClientInstanceMock; +} describe('Cloud Experiments public plugin', () => { jest.spyOn(console, 'debug').mockImplementation(); // silence console.debug logs - beforeEach(() => { - jest.resetAllMocks(); + afterEach(() => { + jest.clearAllMocks(); }); describe('constructor', () => { @@ -29,6 +42,7 @@ describe('Cloud Experiments public plugin', () => { expect(plugin).toHaveProperty('stop'); expect(plugin).toHaveProperty('flagOverrides', undefined); expect(plugin).toHaveProperty('launchDarklyClient', undefined); + expect(plugin).toHaveProperty('metadataService', expect.any(MetadataService)); }); test('fails if launch_darkly is not provided in the config and it is a non-dev environment', () => { @@ -49,17 +63,34 @@ describe('Cloud Experiments public plugin', () => { const plugin = new CloudExperimentsPlugin(initializerContext); expect(plugin).toHaveProperty('flagOverrides', { my_flag: '1234' }); }); + + test('it initializes the LaunchDarkly client', () => { + const initializerContext = coreMock.createPluginInitializerContext({ + launch_darkly: { client_id: 'sdk-1234' }, + }); + const plugin = new CloudExperimentsPlugin(initializerContext); + expect(LaunchDarklyClient).toHaveBeenCalledTimes(1); + expect(plugin).toHaveProperty('launchDarklyClient', expect.any(LaunchDarklyClient)); + }); }); describe('setup', () => { let plugin: CloudExperimentsPlugin; + let metadataServiceSetupSpy: jest.SpyInstance; beforeEach(() => { const initializerContext = coreMock.createPluginInitializerContext({ launch_darkly: { client_id: '1234' }, flag_overrides: { my_flag: '1234' }, + metadata_refresh_interval: duration(1, 'h'), }); plugin = new CloudExperimentsPlugin(initializerContext); + // eslint-disable-next-line dot-notation + metadataServiceSetupSpy = jest.spyOn(plugin['metadataService'], 'setup'); + }); + + afterEach(() => { + plugin.stop(); }); test('returns no contract', () => { @@ -74,37 +105,41 @@ describe('Cloud Experiments public plugin', () => { test('it skips creating the client if no client id provided in the config', () => { const initializerContext = coreMock.createPluginInitializerContext({ flag_overrides: { my_flag: '1234' }, + metadata_refresh_interval: duration(1, 'h'), }); const customPlugin = new CloudExperimentsPlugin(initializerContext); - expect(customPlugin).toHaveProperty('launchDarklyClient', undefined); customPlugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); expect(customPlugin).toHaveProperty('launchDarklyClient', undefined); }); - test('it skips creating the client if cloud is not enabled', () => { - expect(plugin).toHaveProperty('launchDarklyClient', undefined); + test('it skips identifying the user if cloud is not enabled', () => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: false }, }); - expect(plugin).toHaveProperty('launchDarklyClient', undefined); + + expect(metadataServiceSetupSpy).not.toHaveBeenCalled(); }); test('it initializes the LaunchDarkly client', async () => { - expect(plugin).toHaveProperty('launchDarklyClient', undefined); plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); - // await the lazy import - await new Promise((resolve) => process.nextTick(resolve)); - expect(plugin).toHaveProperty('launchDarklyClient', ldClientMock); + + expect(metadataServiceSetupSpy).toHaveBeenCalledWith({ + is_elastic_staff_owned: true, + kibanaVersion: 'version', + trial_end_date: '2020-10-01T14:13:12.000Z', + userId: '1c2412b751f056aef6e340efa5637d137442d489a4b1e3117071e7c87f8523f2', + }); }); }); }); describe('start', () => { let plugin: CloudExperimentsPlugin; + let launchDarklyInstanceMock: jest.Mocked; const firstKnownFlag = Object.keys(FEATURE_FLAG_NAMES)[0] as keyof typeof FEATURE_FLAG_NAMES; @@ -114,11 +149,19 @@ describe('Cloud Experiments public plugin', () => { flag_overrides: { [firstKnownFlag]: '1234' }, }); plugin = new CloudExperimentsPlugin(initializerContext); + launchDarklyInstanceMock = getLaunchDarklyClientInstanceMock(); + }); + + afterEach(() => { + plugin.stop(); }); test('returns the contract', () => { plugin.setup(coreMock.createSetup(), { cloud: cloudMock.createSetup() }); - const startContract = plugin.start(coreMock.createStart()); + const startContract = plugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), + }); expect(startContract).toStrictEqual( expect.objectContaining({ getVariation: expect.any(Function), @@ -127,24 +170,46 @@ describe('Cloud Experiments public plugin', () => { ); }); + test('triggers a userMetadataUpdate for `has_data`', async () => { + plugin.setup(coreMock.createSetup(), { + cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, + }); + + const dataViews = dataViewPluginMocks.createStartContract(); + plugin.start(coreMock.createStart(), { cloud: cloudMock.createStart(), dataViews }); + + // After scheduler kicks in... + await new Promise((resolve) => setTimeout(resolve, 200)); + // Using a timeout of 0ms to let the `timer` kick in. + // For some reason, fakeSchedulers is not working on browser-side tests :shrug: + expect(launchDarklyInstanceMock.updateUserMetadata).toHaveBeenCalledWith( + expect.objectContaining({ + has_data: true, + }) + ); + }); + describe('getVariation', () => { - describe('with the user identified', () => { + let startContract: CloudExperimentsPluginStart; + describe('with the client created', () => { beforeEach(() => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); + startContract = plugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), + }); }); test('uses the flag overrides to respond early', async () => { - const startContract = plugin.start(coreMock.createStart()); await expect(startContract.getVariation(firstKnownFlag, 123)).resolves.toStrictEqual( '1234' ); }); test('calls the client', async () => { - const startContract = plugin.start(coreMock.createStart()); - ldClientMock.variation.mockReturnValue('12345'); + launchDarklyInstanceMock.getVariation.mockResolvedValue('12345'); await expect( startContract.getVariation( // @ts-expect-error We only allow existing flags in FEATURE_FLAG_NAMES @@ -152,29 +217,37 @@ describe('Cloud Experiments public plugin', () => { 123 ) ).resolves.toStrictEqual('12345'); - expect(ldClientMock.variation).toHaveBeenCalledWith( + expect(launchDarklyInstanceMock.getVariation).toHaveBeenCalledWith( undefined, // it couldn't find it in FEATURE_FLAG_NAMES 123 ); }); }); - describe('with the user not identified', () => { + describe('with the client not created', () => { beforeEach(() => { - plugin.setup(coreMock.createSetup(), { - cloud: { ...cloudMock.createSetup(), isCloudEnabled: false }, + const initializerContext = coreMock.createPluginInitializerContext({ + flag_overrides: { [firstKnownFlag]: '1234' }, + metadata_refresh_interval: duration(1, 'h'), + }); + const customPlugin = new CloudExperimentsPlugin(initializerContext); + customPlugin.setup(coreMock.createSetup(), { + cloud: cloudMock.createSetup(), + }); + expect(customPlugin).toHaveProperty('launchDarklyClient', undefined); + startContract = customPlugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), }); }); test('uses the flag overrides to respond early', async () => { - const startContract = plugin.start(coreMock.createStart()); await expect(startContract.getVariation(firstKnownFlag, 123)).resolves.toStrictEqual( '1234' ); }); test('returns the default value without calling the client', async () => { - const startContract = plugin.start(coreMock.createStart()); await expect( startContract.getVariation( // @ts-expect-error We only allow existing flags in FEATURE_FLAG_NAMES @@ -182,28 +255,32 @@ describe('Cloud Experiments public plugin', () => { 123 ) ).resolves.toStrictEqual(123); - expect(ldClientMock.variation).not.toHaveBeenCalled(); + expect(launchDarklyInstanceMock.getVariation).not.toHaveBeenCalled(); }); }); }); describe('reportMetric', () => { - describe('with the user identified', () => { + let startContract: CloudExperimentsPluginStart; + describe('with the client created', () => { beforeEach(() => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); + startContract = plugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), + }); }); test('calls the track API', () => { - const startContract = plugin.start(coreMock.createStart()); startContract.reportMetric({ // @ts-expect-error We only allow existing flags in METRIC_NAMES name: 'my-flag', meta: {}, value: 1, }); - expect(ldClientMock.track).toHaveBeenCalledWith( + expect(launchDarklyInstanceMock.reportMetric).toHaveBeenCalledWith( undefined, // it couldn't find it in METRIC_NAMES {}, 1 @@ -211,22 +288,31 @@ describe('Cloud Experiments public plugin', () => { }); }); - describe('with the user not identified', () => { + describe('with the client not created', () => { beforeEach(() => { - plugin.setup(coreMock.createSetup(), { - cloud: { ...cloudMock.createSetup(), isCloudEnabled: false }, + const initializerContext = coreMock.createPluginInitializerContext({ + flag_overrides: { [firstKnownFlag]: '1234' }, + metadata_refresh_interval: duration(1, 'h'), + }); + const customPlugin = new CloudExperimentsPlugin(initializerContext); + customPlugin.setup(coreMock.createSetup(), { + cloud: cloudMock.createSetup(), + }); + expect(customPlugin).toHaveProperty('launchDarklyClient', undefined); + startContract = customPlugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), }); }); test('calls the track API', () => { - const startContract = plugin.start(coreMock.createStart()); startContract.reportMetric({ // @ts-expect-error We only allow existing flags in METRIC_NAMES name: 'my-flag', meta: {}, value: 1, }); - expect(ldClientMock.track).not.toHaveBeenCalled(); + expect(launchDarklyInstanceMock.reportMetric).not.toHaveBeenCalled(); }); }); }); @@ -234,33 +320,28 @@ describe('Cloud Experiments public plugin', () => { describe('stop', () => { let plugin: CloudExperimentsPlugin; + let launchDarklyInstanceMock: jest.Mocked; beforeEach(() => { const initializerContext = coreMock.createPluginInitializerContext({ launch_darkly: { client_id: '1234' }, flag_overrides: { my_flag: '1234' }, + metadata_refresh_interval: duration(1, 'h'), }); plugin = new CloudExperimentsPlugin(initializerContext); + launchDarklyInstanceMock = getLaunchDarklyClientInstanceMock(); plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); - plugin.start(coreMock.createStart()); + plugin.start(coreMock.createStart(), { + cloud: cloudMock.createStart(), + dataViews: dataViewPluginMocks.createStartContract(), + }); }); test('flushes the events on stop', () => { - ldClientMock.flush.mockResolvedValue(); - expect(() => plugin.stop()).not.toThrow(); - expect(ldClientMock.flush).toHaveBeenCalledTimes(1); - }); - - test('handles errors when flushing events', async () => { - const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - const error = new Error('Something went terribly wrong'); - ldClientMock.flush.mockRejectedValue(error); expect(() => plugin.stop()).not.toThrow(); - expect(ldClientMock.flush).toHaveBeenCalledTimes(1); - await new Promise((resolve) => process.nextTick(resolve)); - expect(consoleWarnSpy).toHaveBeenCalledWith(error); + expect(launchDarklyInstanceMock.stop).toHaveBeenCalledTimes(1); }); }); }); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.ts index 45ca45ab08af1..164d6e45c5294 100755 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/public/plugin.ts @@ -6,29 +6,38 @@ */ import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; -import type { LDClient } from 'launchdarkly-js-client-sdk'; import { get, has } from 'lodash'; +import { duration } from 'moment'; +import { concatMap } from 'rxjs'; import { Sha256 } from '@kbn/crypto-browser'; -import type { CloudSetup } from '@kbn/cloud-plugin/public'; +import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import { LaunchDarklyClient, type LaunchDarklyClientConfig } from './launch_darkly_client'; import type { CloudExperimentsFeatureFlagNames, CloudExperimentsMetric, CloudExperimentsPluginStart, } from '../common'; +import { MetadataService } from '../common/metadata_service'; import { FEATURE_FLAG_NAMES, METRIC_NAMES } from '../common/constants'; interface CloudExperimentsPluginSetupDeps { cloud: CloudSetup; } +interface CloudExperimentsPluginStartDeps { + cloud: CloudStart; + dataViews: DataViewsPublicPluginStart; +} + /** * Browser-side implementation of the Cloud Experiments plugin */ export class CloudExperimentsPlugin implements Plugin { - private launchDarklyClient?: LDClient; - private readonly clientId?: string; + private readonly metadataService: MetadataService; + private readonly launchDarklyClient?: LaunchDarklyClient; private readonly kibanaVersion: string; private readonly flagOverrides?: Record; private readonly isDev: boolean; @@ -38,22 +47,28 @@ export class CloudExperimentsPlugin this.isDev = initializerContext.env.mode.dev; this.kibanaVersion = initializerContext.env.packageInfo.version; const config = initializerContext.config.get<{ - launch_darkly?: { client_id: string }; + launch_darkly?: LaunchDarklyClientConfig; flag_overrides?: Record; + metadata_refresh_interval: string; }>(); + + this.metadataService = new MetadataService({ + metadata_refresh_interval: duration(config.metadata_refresh_interval), + }); + if (config.flag_overrides) { this.flagOverrides = config.flag_overrides; } const ldConfig = config.launch_darkly; - if (!ldConfig && !initializerContext.env.mode.dev) { + if (!ldConfig?.client_id && !initializerContext.env.mode.dev) { // If the plugin is enabled, and it's in prod mode, launch_darkly must exist // (config-schema should enforce it, but just in case). throw new Error( 'xpack.cloud_integrations.experiments.launch_darkly configuration should exist' ); } - if (ldConfig) { - this.clientId = ldConfig.client_id; + if (ldConfig?.client_id) { + this.launchDarklyClient = new LaunchDarklyClient(ldConfig, this.kibanaVersion); } } @@ -63,26 +78,13 @@ export class CloudExperimentsPlugin * @param deps {@link CloudExperimentsPluginSetupDeps} */ public setup(core: CoreSetup, deps: CloudExperimentsPluginSetupDeps) { - if (deps.cloud.isCloudEnabled && deps.cloud.cloudId && this.clientId) { - import('launchdarkly-js-client-sdk').then( - (LaunchDarkly) => { - this.launchDarklyClient = LaunchDarkly.initialize( - this.clientId!, - { - // We use the Hashed Cloud Deployment ID as the userId in the Cloud Experiments - key: sha256(deps.cloud.cloudId!), - custom: { - kibanaVersion: this.kibanaVersion, - }, - }, - { application: { id: 'kibana-browser', version: this.kibanaVersion } } - ); - }, - (err) => { - // eslint-disable-next-line no-console - console.debug(`Error setting up LaunchDarkly: ${err.toString()}`); - } - ); + if (deps.cloud.isCloudEnabled && deps.cloud.cloudId && this.launchDarklyClient) { + this.metadataService.setup({ + userId: sha256(deps.cloud.cloudId), + kibanaVersion: this.kibanaVersion, + trial_end_date: deps.cloud.trialEndDate?.toISOString(), + is_elastic_staff_owned: deps.cloud.isElasticStaffOwned, + }); } } @@ -90,7 +92,26 @@ export class CloudExperimentsPlugin * Returns the contract {@link CloudExperimentsPluginStart} * @param core {@link CoreStart} */ - public start(core: CoreStart): CloudExperimentsPluginStart { + public start( + core: CoreStart, + { cloud, dataViews }: CloudExperimentsPluginStartDeps + ): CloudExperimentsPluginStart { + if (cloud.isCloudEnabled) { + this.metadataService.start({ + hasDataFetcher: async () => ({ has_data: await dataViews.hasData.hasUserDataView() }), + }); + + // We only subscribe to the user metadata updates if Cloud is enabled. + // This way, since the user is not identified, it cannot retrieve Feature Flags from LaunchDarkly when not running on Cloud. + this.metadataService.userMetadata$ + .pipe( + // Using concatMap to ensure we call the promised update in an orderly manner to avoid concurrency issues + concatMap( + async (userMetadata) => await this.launchDarklyClient!.updateUserMetadata(userMetadata) + ) + ) + .subscribe(); // This subscription will stop on when the metadataService stops because it completes the Observable + } return { getVariation: this.getVariation, reportMetric: this.reportMetric, @@ -101,10 +122,8 @@ export class CloudExperimentsPlugin * Cleans up and flush the sending queues. */ public stop() { - this.launchDarklyClient - ?.flush() - // eslint-disable-next-line no-console - .catch((err) => console.warn(err)); + this.launchDarklyClient?.stop(); + this.metadataService.stop(); } private getVariation = async ( @@ -112,18 +131,23 @@ export class CloudExperimentsPlugin defaultValue: Data ): Promise => { const configKey = FEATURE_FLAG_NAMES[featureFlagName]; + // Apply overrides if they exist without asking LaunchDarkly. if (this.flagOverrides && has(this.flagOverrides, configKey)) { return get(this.flagOverrides, configKey, defaultValue) as Data; } - if (!this.launchDarklyClient) return defaultValue; // Skip any action if no LD User is defined - await this.launchDarklyClient.waitForInitialization(); - return this.launchDarklyClient.variation(configKey, defaultValue); + + // Skip any action if no LD Client is defined + if (!this.launchDarklyClient) { + return defaultValue; + } + + return await this.launchDarklyClient.getVariation(configKey, defaultValue); }; private reportMetric = ({ name, meta, value }: CloudExperimentsMetric): void => { const metricName = METRIC_NAMES[name]; - this.launchDarklyClient?.track(metricName, meta, value); + this.launchDarklyClient?.reportMetric(metricName, meta, value); if (this.isDev) { // eslint-disable-next-line no-console console.debug(`Reported experimentation metric ${metricName}`, { diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.test.ts index 2e762ece1d8fe..146de2c3ddc9a 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.test.ts @@ -5,13 +5,17 @@ * 2.0. */ +import moment from 'moment'; import { config } from './config'; describe('cloudExperiments config', () => { describe.each([true, false])('when disabled (dev: %p)', (dev) => { const ctx = { dev }; test('should default to `enabled:false` and the rest empty', () => { - expect(config.schema.validate({}, ctx)).toStrictEqual({ enabled: false }); + expect(config.schema.validate({}, ctx)).toStrictEqual({ + enabled: false, + metadata_refresh_interval: moment.duration(1, 'h'), + }); }); test('it should allow any additional config', () => { @@ -26,7 +30,11 @@ describe('cloudExperiments config', () => { 'my-plugin.my-feature-flag': 1234, }, }; - expect(config.schema.validate(cfg, ctx)).toStrictEqual(cfg); + expect(config.schema.validate(cfg, ctx)).toStrictEqual({ + ...cfg, + // Additional default fields + metadata_refresh_interval: moment.duration(1, 'h'), + }); }); test('it should allow any additional config (missing flag_overrides)', () => { @@ -38,7 +46,10 @@ describe('cloudExperiments config', () => { client_log_level: 'none', }, }; - expect(config.schema.validate(cfg, ctx)).toStrictEqual(cfg); + expect(config.schema.validate(cfg, ctx)).toStrictEqual({ + ...cfg, + metadata_refresh_interval: moment.duration(1, 'h'), + }); }); test('it should allow any additional config (missing launch_darkly)', () => { @@ -48,7 +59,10 @@ describe('cloudExperiments config', () => { 'my-plugin.my-feature-flag': 1234, }, }; - expect(config.schema.validate(cfg, ctx)).toStrictEqual(cfg); + expect(config.schema.validate(cfg, ctx)).toStrictEqual({ + ...cfg, + metadata_refresh_interval: moment.duration(1, 'h'), + }); }); }); @@ -61,11 +75,15 @@ describe('cloudExperiments config', () => { ).toStrictEqual({ enabled: true, flag_overrides: { my_flag: 1 }, + metadata_refresh_interval: moment.duration(1, 'h'), }); }); test('in dev mode, it allows `launch_darkly` and `flag_overrides` to be empty', () => { - expect(config.schema.validate({ enabled: true }, ctx)).toStrictEqual({ enabled: true }); + expect(config.schema.validate({ enabled: true }, ctx)).toStrictEqual({ + enabled: true, + metadata_refresh_interval: moment.duration(1, 'h'), + }); }); }); @@ -98,6 +116,7 @@ describe('cloudExperiments config', () => { client_id: '1234', client_log_level: 'none', }, + metadata_refresh_interval: moment.duration(1, 'h'), }); }); @@ -126,6 +145,7 @@ describe('cloudExperiments config', () => { flag_overrides: { my_flag: 123, }, + metadata_refresh_interval: moment.duration(1, 'h'), }); }); }); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.ts index 79b49bcb77509..a5b5eeb88c2dd 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/config.ts @@ -37,6 +37,7 @@ const configSchema = schema.object({ schema.maybe(launchDarklySchema) ), flag_overrides: schema.maybe(schema.recordOf(schema.string(), schema.any())), + metadata_refresh_interval: schema.duration({ defaultValue: '1h' }), }); export type CloudExperimentsConfigType = TypeOf; @@ -45,8 +46,10 @@ export const config: PluginConfigDescriptor = { exposeToBrowser: { launch_darkly: { client_id: true, + client_log_level: true, }, flag_overrides: true, + metadata_refresh_interval: true, }, schema: configSchema, }; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/index.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/index.ts new file mode 100644 index 0000000000000..d298aad1ad6c1 --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { LaunchDarklyClient, type LaunchDarklyUserMetadata } from './launch_darkly_client'; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.mock.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.mock.ts similarity index 97% rename from x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.mock.ts rename to x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.mock.ts index b76e629458e00..755d565e6b82f 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.mock.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.mock.ts @@ -13,7 +13,6 @@ export function createLaunchDarklyClientMock(): jest.Mocked { variation: jest.fn(), allFlagsState: jest.fn(), track: jest.fn(), - identify: jest.fn(), flush: jest.fn(), } as unknown as jest.Mocked; // Using casting because we only use these APIs. No need to declare everything. } diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.ts new file mode 100644 index 0000000000000..cc140ea44ffdb --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.test.ts @@ -0,0 +1,211 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggerMock, type MockedLogger } from '@kbn/logging-mocks'; +import { ldClientMock } from './launch_darkly_client.test.mock'; +import LaunchDarkly from 'launchdarkly-node-server-sdk'; +import { LaunchDarklyClient, type LaunchDarklyClientConfig } from './launch_darkly_client'; + +describe('LaunchDarklyClient - server', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + const config: LaunchDarklyClientConfig = { + sdk_key: 'fake-sdk-key', + client_id: 'fake-client-id', + client_log_level: 'debug', + kibana_version: 'version', + }; + + describe('constructor', () => { + let launchDarklyInitSpy: jest.SpyInstance; + + beforeEach(() => { + launchDarklyInitSpy = jest.spyOn(LaunchDarkly, 'init'); + }); + + afterEach(() => { + launchDarklyInitSpy.mockRestore(); + }); + + test('it initializes the LaunchDarkly client', async () => { + const logger = loggerMock.create(); + ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); + + const client = new LaunchDarklyClient(config, logger); + expect(launchDarklyInitSpy).toHaveBeenCalledWith('fake-sdk-key', { + application: { id: 'kibana-server', version: 'version' }, + logger: undefined, // The method basicLogger is mocked without a return value + stream: false, + }); + expect(client).toHaveProperty('launchDarklyClient', ldClientMock); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the waitForInitialization resolution + expect(logger.debug).toHaveBeenCalledWith('LaunchDarkly is initialized!'); + }); + + test('it initializes the LaunchDarkly client... and handles failure', async () => { + const logger = loggerMock.create(); + ldClientMock.waitForInitialization.mockRejectedValue( + new Error('Something went terribly wrong') + ); + + const client = new LaunchDarklyClient(config, logger); + expect(launchDarklyInitSpy).toHaveBeenCalledWith('fake-sdk-key', { + application: { id: 'kibana-server', version: 'version' }, + logger: undefined, // The method basicLogger is mocked without a return value + stream: false, + }); + expect(client).toHaveProperty('launchDarklyClient', ldClientMock); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the waitForInitialization resolution + expect(logger.warn).toHaveBeenCalledWith( + 'Error initializing LaunchDarkly: Error: Something went terribly wrong' + ); + }); + }); + + describe('Public APIs', () => { + let client: LaunchDarklyClient; + let logger: MockedLogger; + const testUserMetadata = { userId: 'fake-user-id', kibanaVersion: 'version' }; + + beforeEach(() => { + logger = loggerMock.create(); + ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); + client = new LaunchDarklyClient(config, logger); + }); + + describe('updateUserMetadata', () => { + test('sets the top-level properties at the root (renaming userId to key) and the rest under `custom`', () => { + expect(client).toHaveProperty('launchDarklyUser', undefined); + + const topFields = { + name: 'First Last', + firstName: 'First', + lastName: 'Last', + email: 'first.last@boring.co', + avatar: 'fake-blue-avatar', + ip: 'my-weird-ip', + country: 'distributed', + }; + + const extraFields = { + other_field: 'my other custom field', + kibanaVersion: 'version', + }; + + client.updateUserMetadata({ userId: 'fake-user-id', ...topFields, ...extraFields }); + + expect(client).toHaveProperty('launchDarklyUser', { + key: 'fake-user-id', + ...topFields, + custom: extraFields, + }); + }); + + test('sets a minimum amount of info', () => { + expect(client).toHaveProperty('launchDarklyUser', undefined); + + client.updateUserMetadata({ userId: 'fake-user-id', kibanaVersion: 'version' }); + + expect(client).toHaveProperty('launchDarklyUser', { + key: 'fake-user-id', + custom: { kibanaVersion: 'version' }, + }); + }); + }); + + describe('getVariation', () => { + test('returns the default value if the user has not been defined', async () => { + await expect(client.getVariation('my-feature-flag', 123)).resolves.toStrictEqual(123); + expect(ldClientMock.variation).toHaveBeenCalledTimes(0); + }); + + test('calls the LaunchDarkly client when the user has been defined', async () => { + ldClientMock.variation.mockResolvedValue(1234); + client.updateUserMetadata(testUserMetadata); + await expect(client.getVariation('my-feature-flag', 123)).resolves.toStrictEqual(1234); + expect(ldClientMock.variation).toHaveBeenCalledTimes(1); + expect(ldClientMock.variation).toHaveBeenCalledWith( + 'my-feature-flag', + { key: 'fake-user-id', custom: { kibanaVersion: 'version' } }, + 123 + ); + }); + }); + + describe('reportMetric', () => { + test('does not call track if the user has not been defined', () => { + client.reportMetric('my-feature-flag', {}, 123); + expect(ldClientMock.track).toHaveBeenCalledTimes(0); + }); + + test('calls the LaunchDarkly client when the user has been defined', () => { + client.updateUserMetadata(testUserMetadata); + client.reportMetric('my-feature-flag', {}, 123); + expect(ldClientMock.track).toHaveBeenCalledTimes(1); + expect(ldClientMock.track).toHaveBeenCalledWith( + 'my-feature-flag', + { key: 'fake-user-id', custom: { kibanaVersion: 'version' } }, + {}, + 123 + ); + }); + }); + + describe('getAllFlags', () => { + test('returns the non-initialized state if the user has not been defined', async () => { + await expect(client.getAllFlags()).resolves.toStrictEqual({ + initialized: false, + flagNames: [], + flags: {}, + }); + expect(ldClientMock.allFlagsState).toHaveBeenCalledTimes(0); + }); + + test('calls the LaunchDarkly client when the user has been defined', async () => { + ldClientMock.allFlagsState.mockResolvedValue({ + valid: true, + allValues: jest.fn().mockReturnValue({ my_flag: '1234' }), + getFlagValue: jest.fn(), + getFlagReason: jest.fn(), + toJSON: jest.fn(), + }); + client.updateUserMetadata(testUserMetadata); + await expect(client.getAllFlags()).resolves.toStrictEqual({ + initialized: true, + flagNames: ['my_flag'], + flags: { my_flag: '1234' }, + }); + expect(ldClientMock.allFlagsState).toHaveBeenCalledTimes(1); + expect(ldClientMock.allFlagsState).toHaveBeenCalledWith({ + key: 'fake-user-id', + custom: { kibanaVersion: 'version' }, + }); + }); + }); + + describe('stop', () => { + test('flushes the events', async () => { + ldClientMock.flush.mockResolvedValue(); + expect(() => client.stop()).not.toThrow(); + expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the flush resolution + expect(logger.error).not.toHaveBeenCalled(); + }); + + test('handles errors when flushing events', async () => { + const err = new Error('Something went terribly wrong'); + ldClientMock.flush.mockRejectedValue(err); + expect(() => client.stop()).not.toThrow(); + expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + await new Promise((resolve) => process.nextTick(resolve)); // wait for the flush resolution + expect(logger.error).toHaveBeenCalledWith(err); + }); + }); + }); +}); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.ts new file mode 100644 index 0000000000000..10126e6d48a46 --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/launch_darkly_client.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import LaunchDarkly, { + type LDClient, + type LDFlagSet, + type LDLogLevel, + type LDUser, +} from 'launchdarkly-node-server-sdk'; +import type { Logger } from '@kbn/core/server'; + +export interface LaunchDarklyClientConfig { + sdk_key: string; + client_id: string; + client_log_level: LDLogLevel; + kibana_version: string; +} + +export interface LaunchDarklyUserMetadata + extends Record { + userId: string; + // We are not collecting any of the above, but this is to match the LDUser first-level definition + name?: string; + firstName?: string; + lastName?: string; + email?: string; + avatar?: string; + ip?: string; + country?: string; +} + +export interface LaunchDarklyGetAllFlags { + initialized: boolean; + flags: LDFlagSet; + flagNames: string[]; +} + +export class LaunchDarklyClient { + private readonly launchDarklyClient: LDClient; + private launchDarklyUser?: LDUser; + + constructor(ldConfig: LaunchDarklyClientConfig, private readonly logger: Logger) { + this.launchDarklyClient = LaunchDarkly.init(ldConfig.sdk_key, { + application: { id: `kibana-server`, version: ldConfig.kibana_version }, + logger: LaunchDarkly.basicLogger({ level: ldConfig.client_log_level }), + // For some reason, the stream API does not work in Kibana. `.waitForInitialization()` hangs forever (doesn't throw, neither logs any errors). + // Using polling for now until we resolve that issue. + // Relevant issue: https://github.com/launchdarkly/node-server-sdk/issues/132 + stream: false, + }); + this.launchDarklyClient.waitForInitialization().then( + () => this.logger.debug('LaunchDarkly is initialized!'), + (err) => this.logger.warn(`Error initializing LaunchDarkly: ${err}`) + ); + } + + public updateUserMetadata(userMetadata: LaunchDarklyUserMetadata) { + const { userId, name, firstName, lastName, email, avatar, ip, country, ...custom } = + userMetadata; + this.launchDarklyUser = { + key: userId, + name, + firstName, + lastName, + email, + avatar, + ip, + country, + // This casting is needed because LDUser does not allow `Record` + custom: custom as Record, + }; + } + + public async getVariation(configKey: string, defaultValue: Data): Promise { + if (!this.launchDarklyUser) return defaultValue; // Skip any action if no LD User is defined + await this.launchDarklyClient.waitForInitialization(); + return await this.launchDarklyClient.variation(configKey, this.launchDarklyUser, defaultValue); + } + + public reportMetric(metricName: string, meta?: unknown, value?: number): void { + if (!this.launchDarklyUser) return; // Skip any action if no LD User is defined + this.launchDarklyClient.track(metricName, this.launchDarklyUser, meta, value); + } + + public async getAllFlags(): Promise { + if (!this.launchDarklyUser) return { initialized: false, flagNames: [], flags: {} }; + // According to the docs, this method does not send analytics back to LaunchDarkly, so it does not provide false results + const flagsState = await this.launchDarklyClient.allFlagsState(this.launchDarklyUser); + const flags = flagsState.allValues(); + return { + initialized: flagsState.valid, + flags, + flagNames: Object.keys(flags), + }; + } + + public stop() { + this.launchDarklyClient?.flush().catch((err) => this.logger.error(err)); + } +} diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/mocks.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/mocks.ts new file mode 100644 index 0000000000000..3fe1838815b27 --- /dev/null +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/launch_darkly_client/mocks.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PublicMethodsOf } from '@kbn/utility-types'; +import { LaunchDarklyClient } from './launch_darkly_client'; + +function createLaunchDarklyClientMock(): jest.Mocked { + const launchDarklyClientMock: jest.Mocked> = { + updateUserMetadata: jest.fn(), + getVariation: jest.fn(), + getAllFlags: jest.fn(), + reportMetric: jest.fn(), + stop: jest.fn(), + }; + + return launchDarklyClientMock as jest.Mocked; +} + +export const launchDarklyClientMocks = { + launchDarklyClientMock: createLaunchDarklyClientMock(), + createLaunchDarklyClient: createLaunchDarklyClientMock, +}; diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.ts index aa78353b72329..4d33e0ce65a7d 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.test.ts @@ -5,24 +5,28 @@ * 2.0. */ +import { fakeSchedulers } from 'rxjs-marbles/jest'; import { coreMock } from '@kbn/core/server/mocks'; import { cloudMock } from '@kbn/cloud-plugin/server/mocks'; import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks'; -import { ldClientMock } from './plugin.test.mock'; +import { + createIndexPatternsStartMock, + dataViewsService, +} from '@kbn/data-views-plugin/server/mocks'; +import { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; +import { config } from './config'; import { CloudExperimentsPlugin } from './plugin'; import { FEATURE_FLAG_NAMES } from '../common/constants'; +import { LaunchDarklyClient } from './launch_darkly_client'; +jest.mock('./launch_darkly_client'); describe('Cloud Experiments server plugin', () => { - beforeEach(() => { - jest.resetAllMocks(); - }); + jest.useFakeTimers(); - const ldUser = { - key: '1c2412b751f056aef6e340efa5637d137442d489a4b1e3117071e7c87f8523f2', - custom: { - kibanaVersion: coreMock.createPluginInitializerContext().env.packageInfo.version, - }, - }; + afterEach(() => { + jest.clearAllTimers(); + jest.clearAllMocks(); + }); describe('constructor', () => { test('successfully creates a new plugin if provided an empty configuration', () => { @@ -48,9 +52,9 @@ describe('Cloud Experiments server plugin', () => { const initializerContext = coreMock.createPluginInitializerContext({ launch_darkly: { sdk_key: 'sdk-1234' }, }); - ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); const plugin = new CloudExperimentsPlugin(initializerContext); - expect(plugin).toHaveProperty('launchDarklyClient', ldClientMock); + expect(LaunchDarklyClient).toHaveBeenCalledTimes(1); + expect(plugin).toHaveProperty('launchDarklyClient', expect.any(LaunchDarklyClient)); }); test('it initializes the flagOverrides property', () => { @@ -67,14 +71,22 @@ describe('Cloud Experiments server plugin', () => { let plugin: CloudExperimentsPlugin; beforeEach(() => { - const initializerContext = coreMock.createPluginInitializerContext({ - launch_darkly: { sdk_key: 'sdk-1234' }, - flag_overrides: { my_flag: '1234' }, - }); - ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); + const initializerContext = coreMock.createPluginInitializerContext( + config.schema.validate( + { + launch_darkly: { sdk_key: 'sdk-1234', client_id: 'fake-client-id' }, + flag_overrides: { my_flag: '1234' }, + }, + { dev: true } + ) + ); plugin = new CloudExperimentsPlugin(initializerContext); }); + afterEach(() => { + plugin.stop(); + }); + test('returns the contract', () => { expect( plugin.setup(coreMock.createSetup(), { @@ -93,35 +105,58 @@ describe('Cloud Experiments server plugin', () => { expect(usageCollection.registerCollector).toHaveBeenCalledTimes(1); }); - describe('identifyUser', () => { - test('sets launchDarklyUser and calls identify', () => { - expect(plugin).toHaveProperty('launchDarklyUser', undefined); + test( + 'updates the user metadata on setup', + fakeSchedulers((advance) => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); - expect(plugin).toHaveProperty('launchDarklyUser', ldUser); - expect(ldClientMock.identify).toHaveBeenCalledWith(ldUser); - }); - }); + const launchDarklyInstanceMock = ( + LaunchDarklyClient as jest.MockedClass + ).mock.instances[0]; + advance(100); // Remove the debounceTime effect + expect(launchDarklyInstanceMock.updateUserMetadata).toHaveBeenCalledWith({ + userId: '1c2412b751f056aef6e340efa5637d137442d489a4b1e3117071e7c87f8523f2', + kibanaVersion: coreMock.createPluginInitializerContext().env.packageInfo.version, + is_elastic_staff_owned: true, + trial_end_date: expect.any(String), + }); + }) + ); }); describe('start', () => { let plugin: CloudExperimentsPlugin; + let dataViews: jest.Mocked; + let launchDarklyInstanceMock: jest.Mocked; const firstKnownFlag = Object.keys(FEATURE_FLAG_NAMES)[0] as keyof typeof FEATURE_FLAG_NAMES; beforeEach(() => { - const initializerContext = coreMock.createPluginInitializerContext({ - launch_darkly: { sdk_key: 'sdk-1234' }, - flag_overrides: { [firstKnownFlag]: '1234' }, - }); - ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); + jest.useRealTimers(); + const initializerContext = coreMock.createPluginInitializerContext( + config.schema.validate( + { + launch_darkly: { sdk_key: 'sdk-1234', client_id: 'fake-client-id' }, + flag_overrides: { [firstKnownFlag]: '1234' }, + }, + { dev: true } + ) + ); plugin = new CloudExperimentsPlugin(initializerContext); + dataViews = createIndexPatternsStartMock(); + launchDarklyInstanceMock = (LaunchDarklyClient as jest.MockedClass) + .mock.instances[0] as jest.Mocked; + }); + + afterEach(() => { + plugin.stop(); + jest.useFakeTimers(); }); test('returns the contract', () => { plugin.setup(coreMock.createSetup(), { cloud: cloudMock.createSetup() }); - const startContract = plugin.start(coreMock.createStart()); + const startContract = plugin.start(coreMock.createStart(), { dataViews }); expect(startContract).toStrictEqual( expect.objectContaining({ getVariation: expect.any(Function), @@ -130,8 +165,25 @@ describe('Cloud Experiments server plugin', () => { ); }); + test('triggers a userMetadataUpdate for `has_data`', async () => { + plugin.setup(coreMock.createSetup(), { + cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, + }); + dataViews.dataViewsServiceFactory.mockResolvedValue(dataViewsService); + dataViewsService.hasUserDataView.mockResolvedValue(true); + plugin.start(coreMock.createStart(), { dataViews }); + + // After scheduler kicks in... + await new Promise((resolve) => setTimeout(resolve, 200)); // Waiting for scheduler and debounceTime to complete (don't know why fakeScheduler didn't work here). + expect(launchDarklyInstanceMock.updateUserMetadata).toHaveBeenCalledWith( + expect.objectContaining({ + has_data: true, + }) + ); + }); + describe('getVariation', () => { - describe('with the user identified', () => { + describe('with the client created', () => { beforeEach(() => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, @@ -139,15 +191,15 @@ describe('Cloud Experiments server plugin', () => { }); test('uses the flag overrides to respond early', async () => { - const startContract = plugin.start(coreMock.createStart()); + const startContract = plugin.start(coreMock.createStart(), { dataViews }); await expect(startContract.getVariation(firstKnownFlag, 123)).resolves.toStrictEqual( '1234' ); }); test('calls the client', async () => { - const startContract = plugin.start(coreMock.createStart()); - ldClientMock.variation.mockResolvedValue('12345'); + const startContract = plugin.start(coreMock.createStart(), { dataViews }); + launchDarklyInstanceMock.getVariation.mockResolvedValue('12345'); await expect( startContract.getVariation( // @ts-expect-error We only allow existing flags in FEATURE_FLAG_NAMES @@ -155,30 +207,38 @@ describe('Cloud Experiments server plugin', () => { 123 ) ).resolves.toStrictEqual('12345'); - expect(ldClientMock.variation).toHaveBeenCalledWith( + expect(launchDarklyInstanceMock.getVariation).toHaveBeenCalledWith( undefined, // it couldn't find it in FEATURE_FLAG_NAMES - ldUser, 123 ); }); }); - describe('with the user not identified', () => { + describe('with the client not created (missing LD settings)', () => { beforeEach(() => { + const initializerContext = coreMock.createPluginInitializerContext( + config.schema.validate( + { + flag_overrides: { [firstKnownFlag]: '1234' }, + }, + { dev: true } + ) + ); + plugin = new CloudExperimentsPlugin(initializerContext); plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: false }, }); }); test('uses the flag overrides to respond early', async () => { - const startContract = plugin.start(coreMock.createStart()); + const startContract = plugin.start(coreMock.createStart(), { dataViews }); await expect(startContract.getVariation(firstKnownFlag, 123)).resolves.toStrictEqual( '1234' ); }); test('returns the default value without calling the client', async () => { - const startContract = plugin.start(coreMock.createStart()); + const startContract = plugin.start(coreMock.createStart(), { dataViews }); await expect( startContract.getVariation( // @ts-expect-error We only allow existing flags in FEATURE_FLAG_NAMES @@ -186,52 +246,59 @@ describe('Cloud Experiments server plugin', () => { 123 ) ).resolves.toStrictEqual(123); - expect(ldClientMock.variation).not.toHaveBeenCalled(); }); }); }); describe('reportMetric', () => { - describe('with the user identified', () => { + describe('with the client created', () => { beforeEach(() => { plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); }); - test('calls the track API', () => { - const startContract = plugin.start(coreMock.createStart()); + test('calls LaunchDarklyClient.reportMetric', () => { + const startContract = plugin.start(coreMock.createStart(), { dataViews }); startContract.reportMetric({ // @ts-expect-error We only allow existing flags in METRIC_NAMES name: 'my-flag', meta: {}, value: 1, }); - expect(ldClientMock.track).toHaveBeenCalledWith( + expect(launchDarklyInstanceMock.reportMetric).toHaveBeenCalledWith( undefined, // it couldn't find it in METRIC_NAMES - ldUser, {}, 1 ); }); }); - describe('with the user not identified', () => { + describe('with the client not created (missing LD settings)', () => { beforeEach(() => { + const initializerContext = coreMock.createPluginInitializerContext( + config.schema.validate( + { + flag_overrides: { [firstKnownFlag]: '1234' }, + }, + { dev: true } + ) + ); + plugin = new CloudExperimentsPlugin(initializerContext); plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: false }, }); }); - test('calls the track API', () => { - const startContract = plugin.start(coreMock.createStart()); + test('does not call LaunchDarklyClient.reportMetric because the client is not there', () => { + const startContract = plugin.start(coreMock.createStart(), { dataViews }); startContract.reportMetric({ // @ts-expect-error We only allow existing flags in METRIC_NAMES name: 'my-flag', meta: {}, value: 1, }); - expect(ldClientMock.track).not.toHaveBeenCalled(); + expect(plugin).toHaveProperty('launchDarklyClient', undefined); }); }); }); @@ -241,28 +308,36 @@ describe('Cloud Experiments server plugin', () => { let plugin: CloudExperimentsPlugin; beforeEach(() => { - const initializerContext = coreMock.createPluginInitializerContext({ - launch_darkly: { sdk_key: 'sdk-1234' }, - flag_overrides: { my_flag: '1234' }, - }); - ldClientMock.waitForInitialization.mockResolvedValue(ldClientMock); + const initializerContext = coreMock.createPluginInitializerContext( + config.schema.validate( + { + launch_darkly: { sdk_key: 'sdk-1234', client_id: 'fake-client-id' }, + flag_overrides: { my_flag: '1234' }, + }, + { dev: true } + ) + ); plugin = new CloudExperimentsPlugin(initializerContext); + const dataViews = createIndexPatternsStartMock(); plugin.setup(coreMock.createSetup(), { cloud: { ...cloudMock.createSetup(), isCloudEnabled: true }, }); - plugin.start(coreMock.createStart()); + plugin.start(coreMock.createStart(), { dataViews }); }); - test('flushes the events', () => { - ldClientMock.flush.mockResolvedValue(); - expect(() => plugin.stop()).not.toThrow(); - expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + test('stops the LaunchDarkly client', () => { + plugin.stop(); + const launchDarklyInstanceMock = ( + LaunchDarklyClient as jest.MockedClass + ).mock.instances[0] as jest.Mocked; + expect(launchDarklyInstanceMock.stop).toHaveBeenCalledTimes(1); }); - test('handles errors when flushing events', () => { - ldClientMock.flush.mockRejectedValue(new Error('Something went terribly wrong')); - expect(() => plugin.stop()).not.toThrow(); - expect(ldClientMock.flush).toHaveBeenCalledTimes(1); + test('stops the Metadata Service', () => { + // eslint-disable-next-line dot-notation + const metadataServiceStopSpy = jest.spyOn(plugin['metadataService'], 'stop'); + plugin.stop(); + expect(metadataServiceStopSpy).toHaveBeenCalledTimes(1); }); }); }); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.ts index 782159dc12ab9..093b17934b686 100755 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/plugin.ts @@ -13,11 +13,14 @@ import type { Logger, } from '@kbn/core/server'; import { get, has } from 'lodash'; -import LaunchDarkly, { type LDClient, type LDUser } from 'launchdarkly-node-server-sdk'; import { createSHA256Hash } from '@kbn/crypto'; import type { LogMeta } from '@kbn/logging'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { CloudSetup } from '@kbn/cloud-plugin/server'; +import type { DataViewsServerPluginStart } from '@kbn/data-views-plugin/server/types'; +import { filter, map } from 'rxjs'; +import { MetadataService } from '../common/metadata_service'; +import { LaunchDarklyClient } from './launch_darkly_client'; import { registerUsageCollector } from './usage'; import type { CloudExperimentsConfigType } from './config'; import type { @@ -32,17 +35,26 @@ interface CloudExperimentsPluginSetupDeps { usageCollection?: UsageCollectionSetup; } +interface CloudExperimentsPluginStartDeps { + dataViews: DataViewsServerPluginStart; +} + export class CloudExperimentsPlugin implements Plugin { private readonly logger: Logger; - private readonly launchDarklyClient?: LDClient; + private readonly launchDarklyClient?: LaunchDarklyClient; private readonly flagOverrides?: Record; - private launchDarklyUser: LDUser | undefined; + private readonly metadataService: MetadataService; constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); const config = initializerContext.config.get(); + + this.metadataService = new MetadataService({ + metadata_refresh_interval: config.metadata_refresh_interval, + }); + if (config.flag_overrides) { this.flagOverrides = config.flag_overrides; } @@ -55,17 +67,12 @@ export class CloudExperimentsPlugin ); } if (ldConfig) { - this.launchDarklyClient = LaunchDarkly.init(ldConfig.sdk_key, { - application: { id: `kibana-server`, version: initializerContext.env.packageInfo.version }, - logger: LaunchDarkly.basicLogger({ level: ldConfig.client_log_level }), - // For some reason, the stream API does not work in Kibana. `.waitForInitialization()` hangs forever (doesn't throw, neither logs any errors). - // Using polling for now until we resolve that issue. - // Relevant issue: https://github.com/launchdarkly/node-server-sdk/issues/132 - stream: false, - }); - this.launchDarklyClient.waitForInitialization().then( - () => this.logger.debug('LaunchDarkly is initialized!'), - (err) => this.logger.warn(`Error initializing LaunchDarkly: ${err}`) + this.launchDarklyClient = new LaunchDarklyClient( + { + ...ldConfig, + kibana_version: initializerContext.env.packageInfo.version, + }, + this.logger.get('launch_darkly') ); } } @@ -74,24 +81,33 @@ export class CloudExperimentsPlugin if (deps.usageCollection) { registerUsageCollector(deps.usageCollection, () => ({ launchDarklyClient: this.launchDarklyClient, - launchDarklyUser: this.launchDarklyUser, })); } if (deps.cloud.isCloudEnabled && deps.cloud.cloudId) { - this.launchDarklyUser = { + this.metadataService.setup({ // We use the Cloud ID as the userId in the Cloud Experiments - key: createSHA256Hash(deps.cloud.cloudId), - custom: { - // This list of deployment metadata will likely grow in future versions - kibanaVersion: this.initializerContext.env.packageInfo.version, - }, - }; - this.launchDarklyClient?.identify(this.launchDarklyUser); + userId: createSHA256Hash(deps.cloud.cloudId), + kibanaVersion: this.initializerContext.env.packageInfo.version, + trial_end_date: deps.cloud.trialEndDate?.toISOString(), + is_elastic_staff_owned: deps.cloud.isElasticStaffOwned, + }); + + // We only subscribe to the user metadata updates if Cloud is enabled. + // This way, since the user is not identified, it cannot retrieve Feature Flags from LaunchDarkly when not running on Cloud. + this.metadataService.userMetadata$ + .pipe( + filter(Boolean), // Filter out undefined + map((userMetadata) => this.launchDarklyClient?.updateUserMetadata(userMetadata)) + ) + .subscribe(); // This subscription will stop on when the metadataService stops because it completes the Observable } } - public start(core: CoreStart) { + public start(core: CoreStart, deps: CloudExperimentsPluginStartDeps) { + this.metadataService.start({ + hasDataFetcher: async () => await this.addHasDataMetadata(core, deps.dataViews), + }); return { getVariation: this.getVariation, reportMetric: this.reportMetric, @@ -99,7 +115,8 @@ export class CloudExperimentsPlugin } public stop() { - this.launchDarklyClient?.flush().catch((err) => this.logger.error(err)); + this.launchDarklyClient?.stop(); + this.metadataService.stop(); } private getVariation = async ( @@ -111,15 +128,13 @@ export class CloudExperimentsPlugin if (this.flagOverrides && has(this.flagOverrides, configKey)) { return get(this.flagOverrides, configKey, defaultValue) as Data; } - if (!this.launchDarklyUser) return defaultValue; // Skip any action if no LD User is defined - await this.launchDarklyClient?.waitForInitialization(); - return await this.launchDarklyClient?.variation(configKey, this.launchDarklyUser, defaultValue); + if (!this.launchDarklyClient) return defaultValue; + return await this.launchDarklyClient.getVariation(configKey, defaultValue); }; private reportMetric = ({ name, meta, value }: CloudExperimentsMetric): void => { const metricName = METRIC_NAMES[name]; - if (!this.launchDarklyUser) return; // Skip any action if no LD User is defined - this.launchDarklyClient?.track(metricName, this.launchDarklyUser, meta, value); + this.launchDarklyClient?.reportMetric(metricName, meta, value); this.logger.debug<{ experimentationMetric: CloudExperimentsMetric } & LogMeta>( `Reported experimentation metric ${metricName}`, { @@ -127,4 +142,19 @@ export class CloudExperimentsPlugin } ); }; + + private async addHasDataMetadata( + core: CoreStart, + dataViews: DataViewsServerPluginStart + ): Promise<{ has_data: boolean }> { + const dataViewsService = await dataViews.dataViewsServiceFactory( + core.savedObjects.createInternalRepository(), + core.elasticsearch.client.asInternalUser, + void 0, // No Kibana Request to scope the check + true // Ignore capabilities checks + ); + return { + has_data: await dataViewsService.hasUserDataView(), + }; + } } diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.test.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.test.ts index 176bbad4f6702..ab18c2dbed613 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.test.ts @@ -15,7 +15,7 @@ import { type LaunchDarklyEntitiesGetter, type Usage, } from './register_usage_collector'; -import { createLaunchDarklyClientMock } from '../plugin.test.mock'; +import { launchDarklyClientMocks } from '../launch_darkly_client/mocks'; describe('cloudExperiments usage collector', () => { let collector: Collector; @@ -34,27 +34,7 @@ describe('cloudExperiments usage collector', () => { expect(collector.isReady()).toStrictEqual(true); }); - test('should return initialized false and empty values when the user and the client are not initialized', async () => { - await expect(collector.fetch(createCollectorFetchContextMock())).resolves.toStrictEqual({ - flagNames: [], - flags: {}, - initialized: false, - }); - }); - - test('should return initialized false and empty values when the user is not initialized', async () => { - getLaunchDarklyEntitiesMock.mockReturnValueOnce({ - launchDarklyClient: createLaunchDarklyClientMock(), - }); - await expect(collector.fetch(createCollectorFetchContextMock())).resolves.toStrictEqual({ - flagNames: [], - flags: {}, - initialized: false, - }); - }); - test('should return initialized false and empty values when the client is not initialized', async () => { - getLaunchDarklyEntitiesMock.mockReturnValueOnce({ launchDarklyUser: { key: 'test' } }); await expect(collector.fetch(createCollectorFetchContextMock())).resolves.toStrictEqual({ flagNames: [], flags: {}, @@ -63,21 +43,16 @@ describe('cloudExperiments usage collector', () => { }); test('should return all the flags returned by the client', async () => { - const launchDarklyClient = createLaunchDarklyClientMock(); - getLaunchDarklyEntitiesMock.mockReturnValueOnce({ - launchDarklyClient, - launchDarklyUser: { key: 'test' }, - }); + const launchDarklyClient = launchDarklyClientMocks.createLaunchDarklyClient(); + getLaunchDarklyEntitiesMock.mockReturnValueOnce({ launchDarklyClient }); - launchDarklyClient.allFlagsState.mockResolvedValueOnce({ - valid: true, - getFlagValue: jest.fn(), - getFlagReason: jest.fn(), - toJSON: jest.fn(), - allValues: jest.fn().mockReturnValueOnce({ + launchDarklyClient.getAllFlags.mockResolvedValueOnce({ + initialized: true, + flags: { 'my-plugin.my-feature-flag': true, 'my-plugin.my-other-feature-flag': 22, - }), + }, + flagNames: ['my-plugin.my-feature-flag', 'my-plugin.my-other-feature-flag'], }); await expect(collector.fetch(createCollectorFetchContextMock())).resolves.toStrictEqual({ diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.ts b/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.ts index c9390915fd8c2..9a800dabe9fc8 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.ts +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/server/usage/register_usage_collector.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { LDClient, LDUser } from 'launchdarkly-node-server-sdk'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import type { LaunchDarklyClient } from '../launch_darkly_client'; export interface Usage { initialized: boolean; @@ -15,8 +15,7 @@ export interface Usage { } export type LaunchDarklyEntitiesGetter = () => { - launchDarklyUser?: LDUser; - launchDarklyClient?: LDClient; + launchDarklyClient?: LaunchDarklyClient; }; export function registerUsageCollector( @@ -53,17 +52,9 @@ export function registerUsageCollector( }, }, fetch: async () => { - const { launchDarklyUser, launchDarklyClient } = getLaunchDarklyEntities(); - if (!launchDarklyUser || !launchDarklyClient) - return { initialized: false, flagNames: [], flags: {} }; - // According to the docs, this method does not send analytics back to LaunchDarkly, so it does not provide false results - const flagsState = await launchDarklyClient.allFlagsState(launchDarklyUser); - const flags = flagsState.allValues(); - return { - initialized: flagsState.valid, - flags, - flagNames: Object.keys(flags), - }; + const { launchDarklyClient } = getLaunchDarklyEntities(); + if (!launchDarklyClient) return { initialized: false, flagNames: [], flags: {} }; + return await launchDarklyClient.getAllFlags(); }, }) ); diff --git a/x-pack/plugins/cloud_integrations/cloud_experiments/tsconfig.json b/x-pack/plugins/cloud_integrations/cloud_experiments/tsconfig.json index 917c8c0c9fc53..7f0e98957c5f7 100644 --- a/x-pack/plugins/cloud_integrations/cloud_experiments/tsconfig.json +++ b/x-pack/plugins/cloud_integrations/cloud_experiments/tsconfig.json @@ -15,6 +15,7 @@ ], "references": [ { "path": "../../../../src/core/tsconfig.json" }, + { "path": "../../../../src/plugins/data_views/tsconfig.json" }, { "path": "../../../../src/plugins/usage_collection/tsconfig.json" }, { "path": "../../cloud/tsconfig.json" }, ] diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_search_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_search_bar.tsx index bc7e524ce7bf3..b2272b47c543b 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_search_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_search_bar.tsx @@ -43,7 +43,6 @@ export const FindingsSearchBar = ({ appName={PLUGIN_NAME} dataTestSubj={TEST_SUBJECTS.FINDINGS_SEARCH_BAR} showFilterBar={true} - showQueryBar={true} showQueryInput={true} showDatePicker={false} showSaveQuery={false} diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx index 911eb851924e3..a2eb458bbdf46 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx @@ -110,7 +110,7 @@ export const DocumentCountContent: FC = ({ const ProbabilityUsed = randomSamplerPreference !== RANDOM_SAMPLER_OPTION.OFF && isDefined(samplingProbability) ? ( - <> +
      = ({ defaultMessage="Probability used: {samplingProbability}%" values={{ samplingProbability: samplingProbability * 100 }} /> - +
      ) : null; return ( @@ -127,7 +127,8 @@ export const DocumentCountContent: FC = ({ = ({ size="xs" iconType="gear" onClick={onShowSamplingOptions} - data-test-subj="discoverSamplingOptionsToggle" + data-test-subj="dvRandomSamplerOptionsButton" aria-label={i18n.translate('xpack.dataVisualizer.samplingOptionsButton', { defaultMessage: 'Sampling options', })} @@ -157,6 +158,7 @@ export const DocumentCountContent: FC = ({ = ({ )} > @@ -212,6 +215,7 @@ export const DocumentCountContent: FC = ({ } }} step={RANDOM_SAMPLER_STEP} + data-test-subj="dvRandomSamplerProbabilityRange" /> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts index c2188bab87fe5..310ccde5f9e29 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts @@ -24,20 +24,27 @@ export const RANDOM_SAMPLER_OPTION = { export type RandomSamplerOption = typeof RANDOM_SAMPLER_OPTION[keyof typeof RANDOM_SAMPLER_OPTION]; -export const RANDOM_SAMPLER_SELECT_OPTIONS: Array<{ value: RandomSamplerOption; text: string }> = [ +export const RANDOM_SAMPLER_SELECT_OPTIONS: Array<{ + value: RandomSamplerOption; + text: string; + 'data-test-subj': string; +}> = [ { + 'data-test-subj': 'dvRandomSamplerOptionOnAutomatic', value: RANDOM_SAMPLER_OPTION.ON_AUTOMATIC, text: i18n.translate('xpack.dataVisualizer.randomSamplerPreference.onAutomaticLabel', { defaultMessage: 'On - automatic', }), }, { + 'data-test-subj': 'dvRandomSamplerOptionOnManual', value: RANDOM_SAMPLER_OPTION.ON_MANUAL, text: i18n.translate('xpack.dataVisualizer.randomSamplerPreference.onManualLabel', { defaultMessage: 'On - manual', }), }, { + 'data-test-subj': 'dvRandomSamplerOptionOff', value: RANDOM_SAMPLER_OPTION.OFF, text: i18n.translate('xpack.dataVisualizer.randomSamplerPreference.offLabel', { defaultMessage: 'Off', diff --git a/x-pack/plugins/enterprise_search/common/types/pipelines.ts b/x-pack/plugins/enterprise_search/common/types/pipelines.ts index d6286718b454f..b103b4a5265b3 100644 --- a/x-pack/plugins/enterprise_search/common/types/pipelines.ts +++ b/x-pack/plugins/enterprise_search/common/types/pipelines.ts @@ -8,6 +8,7 @@ import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; export interface InferencePipeline { + modelId: string | undefined; modelState: TrainedModelState; modelStateReason?: string; pipelineName: string; diff --git a/x-pack/plugins/enterprise_search/kibana.json b/x-pack/plugins/enterprise_search/kibana.json index 7cd1e2e71ee7d..4c99ca1df9e0f 100644 --- a/x-pack/plugins/enterprise_search/kibana.json +++ b/x-pack/plugins/enterprise_search/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "requiredPlugins": ["features", "spaces", "security", "licensing", "data", "charts", "infra", "cloud", "esUiShared"], "configPath": ["enterpriseSearch"], - "optionalPlugins": ["usageCollection", "home", "customIntegrations"], + "optionalPlugins": ["usageCollection", "home", "customIntegrations", "ml"], "server": true, "ui": true, "requiredBundles": ["kibanaReact", "cloudChat"], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/pipeline.mock.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/pipeline.mock.ts new file mode 100644 index 0000000000000..55b21f2e4c753 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/__mocks__/pipeline.mock.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IngestPipelineParams } from '../../../../common/types/connectors'; + +export const mockPipelineState: IngestPipelineParams = { + extract_binary_content: true, + name: 'pipeline-name', + reduce_whitespace: true, + run_ml_inference: true, +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/mappings/mappings_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/mappings/mappings_logic.ts index c9530c29b50c3..e0e3db0a2d599 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/mappings/mappings_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/mappings/mappings_logic.ts @@ -10,7 +10,13 @@ import { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; -export const getMappings = async ({ indexName }: { indexName: string }) => { +export interface GetMappingsArgs { + indexName: string; +} + +export type GetMappingsResponse = IndicesGetMappingIndexMappingRecord; + +export const getMappings = async ({ indexName }: GetMappingsArgs) => { const route = `/internal/enterprise_search/mappings/${indexName}`; return await HttpLogic.values.http.get(route); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.test.ts index 9750be9166647..d3a544d4d8c46 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.test.ts @@ -34,7 +34,7 @@ describe('CreateMlInferencePipelineApiLogic', () => { expect(http.post).toHaveBeenCalledWith( '/internal/enterprise_search/indices/unit-test-index/ml_inference/pipeline_processors', { - body: '{"pipeline_name":"unit-test","model_id":"test-model","source_field":"body"}', + body: '{"model_id":"test-model","pipeline_name":"unit-test","source_field":"body"}', } ); expect(result).toEqual({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.ts index 3935cfa30e9f8..ee5e7dd1c4295 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/create_ml_inference_pipeline.ts @@ -8,11 +8,11 @@ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; export interface CreateMlInferencePipelineApiLogicArgs { + destinationField?: string; indexName: string; - pipelineName: string; modelId: string; + pipelineName: string; sourceField: string; - destinationField?: string; } export interface CreateMlInferencePipelineResponse { @@ -24,10 +24,10 @@ export const createMlInferencePipeline = async ( ): Promise => { const route = `/internal/enterprise_search/indices/${args.indexName}/ml_inference/pipeline_processors`; const params = { - pipeline_name: args.pipelineName, + destination_field: args.destinationField, model_id: args.modelId, + pipeline_name: args.pipelineName, source_field: args.sourceField, - destination_field: args.destinationField, }; return await HttpLogic.values.http.post(route, { body: JSON.stringify(params), diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts index 0f0ead7bb0642..a0d86a821afd3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/ml_models/ml_models_logic.ts @@ -9,7 +9,11 @@ import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; -export const getMLModels = async (size: number = 1000) => { +export type GetMlModelsArgs = number | undefined; + +export type GetMlModelsResponse = TrainedModelConfigResponse[]; + +export const getMLModels = async (size: GetMlModelsArgs = 1000) => { return await HttpLogic.values.http.get('/api/ml/trained_models', { query: { size, with_pipelines: true }, }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/simulate_ml_inference_pipeline_processors.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/simulate_ml_inference_pipeline_processors.ts new file mode 100644 index 0000000000000..18c90fbd7e6c1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/simulate_ml_inference_pipeline_processors.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IngestSimulateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + +import type { MlInferencePipeline } from '../../../../../common/types/pipelines'; + +import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; + +import { HttpLogic } from '../../../shared/http'; + +export interface SimulateMlInterfacePipelineArgs { + docs: string; + indexName: string; + pipeline: MlInferencePipeline; +} +export type SimulateMlInterfacePipelineResponse = IngestSimulateResponse; + +export const simulateMlInferencePipeline = async ({ + docs, + indexName, + pipeline, +}: SimulateMlInterfacePipelineArgs) => { + const route = `/internal/enterprise_search/indices/${indexName}/ml_inference/pipeline_processors/simulate`; + + return await HttpLogic.values.http.post(route, { + body: JSON.stringify({ + docs, + pipeline: { + description: pipeline.description, + processors: pipeline.processors, + }, + }), + }); +}; + +export const SimulateMlInterfacePipelineApiLogic = createApiLogic( + ['simulate_ml_inference_pipeline_api_logic'], + simulateMlInferencePipeline +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx index 79f344e5119e4..0b927e4d01f4b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.test.tsx @@ -19,6 +19,7 @@ import { InferencePipelineCard } from './inference_pipeline_card'; import { TrainedModelHealth } from './ml_model_health'; export const DEFAULT_VALUES: InferencePipeline = { + modelId: 'sample-bert-ner-model', modelState: TrainedModelState.Started, pipelineName: 'Sample Processor', types: ['pytorch', 'ner'], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.test.tsx new file mode 100644 index 0000000000000..1aa74f8957670 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiBadge } from '@elastic/eui'; + +import { EuiButtonEmptyTo } from '../../../../../shared/react_router_helpers'; + +import { CustomPipelineItem } from './custom_pipeline_item'; + +describe('CustomPipelineItem', () => { + it('renders custom pipeline item', () => { + const indexName = 'fake-index-name'; + const pipelineSuffix = 'custom-pipeline'; + const ingestionMethod = 'crawler'; + const processorsCount = 12; + + const wrapper = shallow( + + ); + const title = wrapper.find('h4').text(); + const editLink = wrapper.find(EuiButtonEmptyTo).prop('to'); + const trackLink = wrapper.find(EuiButtonEmptyTo).prop('data-telemetry-id'); + const processorCountBadge = wrapper.find(EuiBadge).render().text(); + + expect(title).toEqual(`${indexName}@${pipelineSuffix}`); + expect(editLink.endsWith(`${indexName}@${pipelineSuffix}`)).toBe(true); + expect(trackLink).toEqual( + `entSearchContent-${ingestionMethod}-pipelines-customPipeline-editPipeline` + ); + expect(processorCountBadge).toEqual(`${processorsCount} Processors`); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/custom_pipeline_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.tsx similarity index 95% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/custom_pipeline_panel.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.tsx index 0a15e03eb2326..54471840aff4d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/custom_pipeline_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/custom_pipeline_item.tsx @@ -11,9 +11,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText, EuiBadge } from '@elastic import { i18n } from '@kbn/i18n'; -import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; +import { EuiButtonEmptyTo } from '../../../../../shared/react_router_helpers'; -export const CustomPipelinePanel: React.FC<{ +export const CustomPipelineItem: React.FC<{ indexName: string; ingestionMethod: string; pipelineSuffix: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx new file mode 100644 index 0000000000000..29bcd0b03dbd3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockPipelineState } from '../../../../__mocks__/pipeline.mock'; +import { indices } from '../../../../__mocks__/search_indices.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiBadge, EuiButtonEmpty } from '@elastic/eui'; + +import { CurlRequest } from '../../components/curl_request/curl_request'; + +import { DefaultPipelineItem } from './default_pipeline_item'; + +describe('DefaultPipelineItem', () => { + it('renders default pipeline item for ingestion indices', () => { + const index = indices[1]; + const mockOpenModal = jest.fn(); + const ingestionMethod = 'connector'; + const wrapper = shallow( + + ); + + const title = wrapper.find('h4').text(); + const settingsButton = wrapper.find(EuiButtonEmpty); + const curlRequest = wrapper.find(CurlRequest); + const badge = wrapper.find(EuiBadge); + + expect(title).toEqual(mockPipelineState.name); + expect(settingsButton.prop('data-telemetry-id')).toEqual( + `entSearchContent-${ingestionMethod}-pipelines-ingestPipelines-settings` + ); + settingsButton.simulate('click'); + expect(mockOpenModal).toHaveBeenCalledTimes(1); + expect(curlRequest.length).toEqual(0); + expect(badge.render().text()).toEqual('Managed'); + }); + + it('renders default pipeline item for api indices', () => { + const index = indices[0]; + const mockOpenModal = jest.fn(); + const ingestionMethod = 'api'; + const wrapper = shallow( + + ); + + const title = wrapper.find('h4').text(); + const settingsButton = wrapper.find(EuiButtonEmpty); + const curlRequest = wrapper.find(CurlRequest); + const badge = wrapper.find(EuiBadge); + + expect(title).toEqual(mockPipelineState.name); + expect(settingsButton.prop('data-telemetry-id')).toEqual( + `entSearchContent-${ingestionMethod}-pipelines-ingestPipelines-settings` + ); + settingsButton.simulate('click'); + expect(mockOpenModal).toHaveBeenCalledTimes(1); + expect(curlRequest.prop('document')).toBeDefined(); + expect(curlRequest.prop('indexName')).toEqual(index.name); + expect(curlRequest.prop('pipeline')).toEqual({ + ...mockPipelineState, + name: mockPipelineState.name, + }); + + expect(badge.render().text()).toEqual('Managed'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx new file mode 100644 index 0000000000000..c22f7910bdc4f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + EuiAccordion, + EuiBadge, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiTitle, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { IngestPipelineParams } from '../../../../../../../common/types/connectors'; +import { ElasticsearchIndexWithIngestion } from '../../../../../../../common/types/indices'; + +import { isApiIndex } from '../../../../utils/indices'; +import { CurlRequest } from '../../components/curl_request/curl_request'; + +export const DefaultPipelineItem: React.FC<{ + index: ElasticsearchIndexWithIngestion; + indexName: string; + ingestionMethod: string; + openModal: () => void; + pipelineName: string; + pipelineState: IngestPipelineParams; +}> = ({ index, indexName, ingestionMethod, openModal, pipelineName, pipelineState }) => { + return ( + + + + + +

      {pipelineName}

      +
      +
      + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.settings.label', + { defaultMessage: 'Settings' } + )} + + +
      +
      + + + {isApiIndex(index) && ( + + + + + + )} + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.managedBadge.label', + { defaultMessage: 'Managed' } + )} + + + + +
      + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipeline_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx similarity index 96% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipeline_modal.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx index 34cb59e734d70..6be65b6387d49 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipeline_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx @@ -27,13 +27,13 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { DEFAULT_PIPELINE_NAME } from '../../../../../../common/constants'; +import { DEFAULT_PIPELINE_NAME } from '../../../../../../../common/constants'; -import { IngestPipelineParams } from '../../../../../../common/types/connectors'; +import { IngestPipelineParams } from '../../../../../../../common/types/connectors'; -import { CurlRequest } from '../components/curl_request/curl_request'; +import { CurlRequest } from '../../components/curl_request/curl_request'; -import { PipelineSettingsForm } from './pipeline_settings_form'; +import { PipelineSettingsForm } from '../pipeline_settings_form'; interface IngestPipelineModalProps { closeModal: () => void; @@ -46,7 +46,6 @@ interface IngestPipelineModalProps { pipeline: IngestPipelineParams; savePipeline: () => void; setPipeline: (pipeline: IngestPipelineParams) => void; - showModal: boolean; } export const IngestPipelineModal: React.FC = ({ @@ -60,14 +59,13 @@ export const IngestPipelineModal: React.FC = ({ pipeline, savePipeline, setPipeline, - showModal, }) => { const { name } = pipeline; // can't customize if you already have a custom pipeline! const canCustomize = name === DEFAULT_PIPELINE_NAME; - return showModal ? ( + return ( @@ -260,7 +258,5 @@ export const IngestPipelineModal: React.FC = ({ )} - ) : ( - <> ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx new file mode 100644 index 0000000000000..7406d9e89150b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect } from 'react'; + +import { useActions, useValues } from 'kea'; + +import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + +import { KibanaLogic } from '../../../../../shared/kibana'; + +import { LicensingLogic } from '../../../../../shared/licensing'; +import { CreateCustomPipelineApiLogic } from '../../../../api/index/create_custom_pipeline_api_logic'; +import { FetchCustomPipelineApiLogic } from '../../../../api/index/fetch_custom_pipeline_api_logic'; +import { IndexViewLogic } from '../../index_view_logic'; + +import { PipelinesLogic } from '../pipelines_logic'; + +import { CustomPipelineItem } from './custom_pipeline_item'; +import { DefaultPipelineItem } from './default_pipeline_item'; +import { IngestPipelineModal } from './ingest_pipeline_modal'; + +export const IngestPipelinesCard: React.FC = () => { + const { indexName, ingestionMethod } = useValues(IndexViewLogic); + + const { canSetPipeline, index, pipelineName, pipelineState, showModal } = + useValues(PipelinesLogic); + const { closeModal, openModal, setPipelineState, savePipeline } = useActions(PipelinesLogic); + const { makeRequest: fetchCustomPipeline } = useActions(FetchCustomPipelineApiLogic); + const { makeRequest: createCustomPipeline } = useActions(CreateCustomPipelineApiLogic); + const { data: customPipelines } = useValues(FetchCustomPipelineApiLogic); + const { isCloud } = useValues(KibanaLogic); + const { hasPlatinumLicense } = useValues(LicensingLogic); + + const isGated = !isCloud && !hasPlatinumLicense; + const customPipeline = customPipelines ? customPipelines[`${indexName}@custom`] : undefined; + + useEffect(() => { + fetchCustomPipeline({ indexName }); + }, [indexName]); + + return ( + + {showModal && ( + createCustomPipeline({ indexName })} + displayOnly={!canSetPipeline} + indexName={indexName} + ingestionMethod={ingestionMethod} + isGated={isGated} + isLoading={false} + pipeline={{ ...pipelineState, name: pipelineName }} + savePipeline={savePipeline} + setPipeline={setPipelineState} + /> + )} + + + + + + {customPipeline && ( + + + + + + )} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines_card.tsx deleted file mode 100644 index 711d83f11bdea..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines_card.tsx +++ /dev/null @@ -1,141 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect } from 'react'; - -import { useActions, useValues } from 'kea'; - -import { - EuiPanel, - EuiFlexGroup, - EuiFlexItem, - EuiTitle, - EuiButtonEmpty, - EuiAccordion, - EuiBadge, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; - -import { KibanaLogic } from '../../../../shared/kibana'; - -import { LicensingLogic } from '../../../../shared/licensing'; -import { CreateCustomPipelineApiLogic } from '../../../api/index/create_custom_pipeline_api_logic'; -import { FetchCustomPipelineApiLogic } from '../../../api/index/fetch_custom_pipeline_api_logic'; -import { isApiIndex } from '../../../utils/indices'; -import { CurlRequest } from '../components/curl_request/curl_request'; -import { IndexViewLogic } from '../index_view_logic'; - -import { CustomPipelinePanel } from './custom_pipeline_panel'; -import { IngestPipelineModal } from './ingest_pipeline_modal'; -import { PipelinesLogic } from './pipelines_logic'; - -export const IngestPipelinesCard: React.FC = () => { - const { indexName, ingestionMethod } = useValues(IndexViewLogic); - - const { canSetPipeline, index, pipelineName, pipelineState, showModal } = - useValues(PipelinesLogic); - const { closeModal, openModal, setPipelineState, savePipeline } = useActions(PipelinesLogic); - const { makeRequest: fetchCustomPipeline } = useActions(FetchCustomPipelineApiLogic); - const { makeRequest: createCustomPipeline } = useActions(CreateCustomPipelineApiLogic); - const { data: customPipelines } = useValues(FetchCustomPipelineApiLogic); - const { isCloud } = useValues(KibanaLogic); - const { hasPlatinumLicense } = useValues(LicensingLogic); - - const isGated = !isCloud && !hasPlatinumLicense; - const customPipeline = customPipelines ? customPipelines[`${indexName}@custom`] : undefined; - - useEffect(() => { - fetchCustomPipeline({ indexName }); - }, [indexName]); - - return ( - - createCustomPipeline({ indexName })} - displayOnly={!canSetPipeline} - indexName={indexName} - ingestionMethod={ingestionMethod} - isGated={isGated} - isLoading={false} - pipeline={{ ...pipelineState, name: pipelineName }} - savePipeline={savePipeline} - setPipeline={setPipelineState} - showModal={showModal} - /> - {customPipeline && ( - - - - - - )} - - - - - - - -

      {pipelineName}

      -
      -
      - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.settings.label', - { defaultMessage: 'Settings' } - )} - - -
      -
      - - - {isApiIndex(index) && ( - - - - - - )} - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.managedBadge.label', - { defaultMessage: 'Managed' } - )} - - - - -
      -
      -
      -
      - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.scss b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.scss new file mode 100644 index 0000000000000..cd3c318635932 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.scss @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +.enterpriseSearchInferencePipelineModal { + width: $euiSizeXXL * 20; + + .resizableContainer { + min-height: $euiSizeXL * 10; + + .reviewCodeBlock { + height: 100%; + } + } +} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.tsx index 99faa4920108c..edbf18f8b009c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_pipeline_modal.tsx @@ -43,6 +43,8 @@ import { NoModelsPanel } from './no_models'; import { ReviewPipeline } from './review_pipeline'; import { TestPipeline } from './test_pipeline'; +import './add_ml_inference_pipeline_modal.scss'; + interface AddMLInferencePipelineModalProps { onClose: () => void; } @@ -57,7 +59,7 @@ export const AddMLInferencePipelineModal: React.FC +

      @@ -141,7 +143,10 @@ const ModalSteps: React.FC = () => { ), }, { - onClick: () => setAddInferencePipelineStep(AddInferencePipelineSteps.Test), + onClick: () => { + if (!isPipelineDataValid) return; + setAddInferencePipelineStep(AddInferencePipelineSteps.Test); + }, status: isPipelineDataValid ? 'incomplete' : 'disabled', title: i18n.translate( 'xpack.enterpriseSearch.content.indices.transforms.addInferencePipelineModal.steps.test.title', @@ -151,7 +156,10 @@ const ModalSteps: React.FC = () => { ), }, { - onClick: () => setAddInferencePipelineStep(AddInferencePipelineSteps.Review), + onClick: () => { + if (!isPipelineDataValid) return; + setAddInferencePipelineStep(AddInferencePipelineSteps.Review); + }, status: isPipelineDataValid ? 'incomplete' : 'disabled', title: i18n.translate( 'xpack.enterpriseSearch.content.indices.transforms.addInferencePipelineModal.steps.review.title', @@ -227,14 +235,16 @@ const ModalFooter: React.FC setAddInferencePipelineStep(nextStep as AddInferencePipelineSteps)} disabled={!isPipelineDataValid} + fill > {CONTINUE_BUTTON_LABEL} ) : ( {i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts new file mode 100644 index 0000000000000..f0222becb7961 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.test.ts @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { LogicMounter } from '../../../../../__mocks__/kea_logic'; + +import { HttpError, Status } from '../../../../../../../common/types/api'; + +import { MappingsApiLogic } from '../../../../api/mappings/mappings_logic'; +import { CreateMlInferencePipelineApiLogic } from '../../../../api/ml_models/create_ml_inference_pipeline'; +import { MLModelsApiLogic } from '../../../../api/ml_models/ml_models_logic'; +import { SimulateMlInterfacePipelineApiLogic } from '../../../../api/pipelines/simulate_ml_inference_pipeline_processors'; + +import { + MLInferenceLogic, + EMPTY_PIPELINE_CONFIGURATION, + AddInferencePipelineSteps, +} from './ml_inference_logic'; + +const DEFAULT_VALUES = { + addInferencePipelineModal: { + configuration: { + ...EMPTY_PIPELINE_CONFIGURATION, + }, + indexName: '', + simulateBody: ` +[ + { + "_index": "index", + "_id": "id", + "_source": { + "foo": "bar" + } + }, + { + "_index": "index", + "_id": "id", + "_source": { + "foo": "baz" + } + } +]`, + step: AddInferencePipelineSteps.Configuration, + }, + createErrors: [], + formErrors: { + modelID: 'Field is required.', + pipelineName: 'Field is required.', + sourceField: 'Field is required.', + }, + index: undefined, + isLoading: true, + isPipelineDataValid: false, + mappingData: undefined, + mappingStatus: 0, + mlInferencePipeline: undefined, + mlModelsData: undefined, + mlModelsStatus: 0, + simulatePipelineData: undefined, + simulatePipelineErrors: [], + simulatePipelineResult: undefined, + simulatePipelineStatus: 0, + sourceFields: undefined, + supportedMLModels: undefined, +}; + +describe('MlInferenceLogic', () => { + const { mount } = new LogicMounter(MLInferenceLogic); + const { mount: mountMappingApiLogic } = new LogicMounter(MappingsApiLogic); + const { mount: mountMLModelsApiLogic } = new LogicMounter(MLModelsApiLogic); + const { mount: mountSimulateMlInterfacePipelineApiLogic } = new LogicMounter( + SimulateMlInterfacePipelineApiLogic + ); + const { mount: mountCreateMlInferencePipelineApiLogic } = new LogicMounter( + CreateMlInferencePipelineApiLogic + ); + + beforeEach(() => { + jest.clearAllMocks(); + mountMappingApiLogic(); + mountMLModelsApiLogic(); + mountSimulateMlInterfacePipelineApiLogic(); + mountCreateMlInferencePipelineApiLogic(); + mount(); + }); + + it('has expected default values', () => { + expect(MLInferenceLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + describe('setSimulatePipelineErrors', () => { + it('sets simulatePipelineErrors to passed payload', () => { + expect(MLInferenceLogic.values).toEqual(DEFAULT_VALUES); + + MLInferenceLogic.actions.setSimulatePipelineErrors([ + 'I would be an error coming from Backend', + 'I would be another one', + ]); + + expect(MLInferenceLogic.values).toEqual({ + ...DEFAULT_VALUES, + simulatePipelineErrors: [ + 'I would be an error coming from Backend', + 'I would be another one', + ], + }); + }); + }); + }); + + describe('selectors', () => { + describe('simulatePipelineResult', () => { + it('returns undefined if simulatePipelineStatus is not success', () => { + SimulateMlInterfacePipelineApiLogic.actions.apiError({} as HttpError); + expect(MLInferenceLogic.values).toEqual({ + ...DEFAULT_VALUES, + simulatePipelineErrors: ['An unexpected error occurred'], + simulatePipelineResult: undefined, + simulatePipelineStatus: Status.ERROR, + }); + }); + it('returns simulation result when API is successful', () => { + const simulateResponse = { + docs: [ + { + doc: { + _id: 'id', + _index: 'index', + _ingest: { timestamp: '2022-10-06T10:28:54.3326245Z' }, + _source: { + _ingest: { + inference_errors: [ + { + message: + "Processor 'inference' in pipeline 'test' failed with message 'Input field [text_field] does not exist in the source document'", + pipeline: 'guy', + timestamp: '2022-10-06T10:28:54.332624500Z', + }, + ], + processors: [ + { + model_version: '8.6.0', + pipeline: 'guy', + processed_timestamp: '2022-10-06T10:28:54.332624500Z', + types: ['pytorch', 'ner'], + }, + ], + }, + _version: '-3', + foo: 'bar', + }, + }, + }, + ], + }; + SimulateMlInterfacePipelineApiLogic.actions.apiSuccess(simulateResponse); + + expect(MLInferenceLogic.values.simulatePipelineResult).toEqual(simulateResponse); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.ts index 082644b12c6ea..6488ca0723142 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/ml_inference_logic.ts @@ -8,6 +8,7 @@ import { kea, MakeLogicType } from 'kea'; import { IndicesGetMappingIndexMappingRecord } from '@elastic/elasticsearch/lib/api/types'; +import { IngestSimulateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; @@ -15,22 +16,41 @@ import { formatPipelineName, generateMlInferencePipelineBody, } from '../../../../../../../common/ml_inference_pipeline'; -import { HttpError, Status } from '../../../../../../../common/types/api'; +import { Status } from '../../../../../../../common/types/api'; import { MlInferencePipeline } from '../../../../../../../common/types/pipelines'; +import { Actions } from '../../../../../shared/api_logic/create_api_logic'; import { getErrorsFromHttpResponse } from '../../../../../shared/flash_messages/handle_api_errors'; import { FetchIndexApiLogic, FetchIndexApiResponse, } from '../../../../api/index/fetch_index_api_logic'; -import { MappingsApiLogic } from '../../../../api/mappings/mappings_logic'; -import { CreateMlInferencePipelineApiLogic } from '../../../../api/ml_models/create_ml_inference_pipeline'; -import { MLModelsApiLogic } from '../../../../api/ml_models/ml_models_logic'; +import { + GetMappingsArgs, + GetMappingsResponse, + MappingsApiLogic, +} from '../../../../api/mappings/mappings_logic'; +import { + CreateMlInferencePipelineApiLogic, + CreateMlInferencePipelineApiLogicArgs, + CreateMlInferencePipelineResponse, +} from '../../../../api/ml_models/create_ml_inference_pipeline'; +import { + GetMlModelsArgs, + GetMlModelsResponse, + MLModelsApiLogic, +} from '../../../../api/ml_models/ml_models_logic'; +import { + SimulateMlInterfacePipelineApiLogic, + SimulateMlInterfacePipelineArgs, + SimulateMlInterfacePipelineResponse, +} from '../../../../api/pipelines/simulate_ml_inference_pipeline_processors'; import { isConnectorIndex } from '../../../../utils/indices'; import { isSupportedMLModel, sortSourceFields } from '../../../shared/ml_inference/utils'; import { AddInferencePipelineFormErrors, InferencePipelineConfiguration } from './types'; + import { validateInferencePipelineConfiguration } from './utils'; export const EMPTY_PIPELINE_CONFIGURATION: InferencePipelineConfiguration = { @@ -50,14 +70,27 @@ const API_REQUEST_COMPLETE_STATUSES = [Status.SUCCESS, Status.ERROR]; const DEFAULT_CONNECTOR_FIELDS = ['body', 'title', 'id', 'type', 'url']; interface MLInferenceProcessorsActions { - createApiError: (error: HttpError) => HttpError; - createApiSuccess: typeof CreateMlInferencePipelineApiLogic.actions.apiSuccess; + createApiError: Actions< + CreateMlInferencePipelineApiLogicArgs, + CreateMlInferencePipelineResponse + >['apiError']; + createApiSuccess: Actions< + CreateMlInferencePipelineApiLogicArgs, + CreateMlInferencePipelineResponse + >['apiSuccess']; createPipeline: () => void; - makeCreatePipelineRequest: typeof CreateMlInferencePipelineApiLogic.actions.makeRequest; - makeMLModelsRequest: typeof MLModelsApiLogic.actions.makeRequest; - makeMappingRequest: typeof MappingsApiLogic.actions.makeRequest; - mappingsApiError(error: HttpError): HttpError; - mlModelsApiError(error: HttpError): HttpError; + makeCreatePipelineRequest: Actions< + CreateMlInferencePipelineApiLogicArgs, + CreateMlInferencePipelineResponse + >['makeRequest']; + makeMLModelsRequest: Actions['makeRequest']; + makeMappingRequest: Actions['makeRequest']; + makeSimulatePipelineRequest: Actions< + SimulateMlInterfacePipelineArgs, + SimulateMlInterfacePipelineResponse + >['makeRequest']; + mappingsApiError: Actions['apiError']; + mlModelsApiError: Actions['apiError']; setAddInferencePipelineStep: (step: AddInferencePipelineSteps) => { step: AddInferencePipelineSteps; }; @@ -66,11 +99,25 @@ interface MLInferenceProcessorsActions { setInferencePipelineConfiguration: (configuration: InferencePipelineConfiguration) => { configuration: InferencePipelineConfiguration; }; + setPipelineSimulateBody: (simulateBody: string) => { + simulateBody: string; + }; + setSimulatePipelineErrors(errors: string[]): { errors: string[] }; + simulatePipeline: () => void; + simulatePipelineApiError: Actions< + SimulateMlInterfacePipelineArgs, + SimulateMlInterfacePipelineResponse + >['apiError']; + simulatePipelineApiSuccess: Actions< + SimulateMlInterfacePipelineArgs, + SimulateMlInterfacePipelineResponse + >['apiSuccess']; } export interface AddInferencePipelineModal { configuration: InferencePipelineConfiguration; indexName: string; + simulateBody: string; step: AddInferencePipelineSteps; } @@ -78,14 +125,18 @@ interface MLInferenceProcessorsValues { addInferencePipelineModal: AddInferencePipelineModal; createErrors: string[]; formErrors: AddInferencePipelineFormErrors; + index: FetchIndexApiResponse; isLoading: boolean; isPipelineDataValid: boolean; - index: FetchIndexApiResponse; mappingData: typeof MappingsApiLogic.values.data; mappingStatus: Status; mlInferencePipeline?: MlInferencePipeline; mlModelsData: typeof MLModelsApiLogic.values.data; - mlModelsStatus: typeof MLModelsApiLogic.values.apiStatus; + mlModelsStatus: Status; + simulatePipelineData: typeof SimulateMlInterfacePipelineApiLogic.values.data; + simulatePipelineErrors: string[]; + simulatePipelineResult: IngestSimulateResponse; + simulatePipelineStatus: Status; sourceFields: string[] | undefined; supportedMLModels: typeof MLModelsApiLogic.values.data; } @@ -103,6 +154,11 @@ export const MLInferenceLogic = kea< setInferencePipelineConfiguration: (configuration: InferencePipelineConfiguration) => ({ configuration, }), + setPipelineSimulateBody: (simulateBody: string) => ({ + simulateBody, + }), + setSimulatePipelineErrors: (errors: string[]) => ({ errors }), + simulatePipeline: true, }, connect: { actions: [ @@ -110,6 +166,12 @@ export const MLInferenceLogic = kea< ['makeRequest as makeMappingRequest', 'apiError as mappingsApiError'], MLModelsApiLogic, ['makeRequest as makeMLModelsRequest', 'apiError as mlModelsApiError'], + SimulateMlInterfacePipelineApiLogic, + [ + 'makeRequest as makeSimulatePipelineRequest', + 'apiSuccess as simulatePipelineApiSuccess', + 'apiError as simulatePipelineApiError', + ], CreateMlInferencePipelineApiLogic, [ 'apiError as createApiError', @@ -124,6 +186,8 @@ export const MLInferenceLogic = kea< ['data as mappingData', 'status as mappingStatus'], MLModelsApiLogic, ['data as mlModelsData', 'status as mlModelsStatus'], + SimulateMlInterfacePipelineApiLogic, + ['data as simulatePipelineData', 'status as simulatePipelineStatus'], ], }, events: {}, @@ -134,14 +198,14 @@ export const MLInferenceLogic = kea< } = values; actions.makeCreatePipelineRequest({ - indexName, - pipelineName: configuration.pipelineName, - modelId: configuration.modelID, - sourceField: configuration.sourceField, destinationField: configuration.destinationField.trim().length > 0 ? configuration.destinationField : undefined, + indexName, + modelId: configuration.modelID, + pipelineName: configuration.pipelineName, + sourceField: configuration.sourceField, }); }, makeCreatePipelineRequest: () => actions.setCreateErrors([]), @@ -149,6 +213,16 @@ export const MLInferenceLogic = kea< actions.makeMLModelsRequest(undefined); actions.makeMappingRequest({ indexName }); }, + simulatePipeline: () => { + if (values.mlInferencePipeline) { + actions.setSimulatePipelineErrors([]); + actions.makeSimulatePipelineRequest({ + docs: values.addInferencePipelineModal.simulateBody, + indexName: values.addInferencePipelineModal.indexName, + pipeline: values.mlInferencePipeline, + }); + } + }, }), path: ['enterprise_search', 'content', 'pipelines_add_ml_inference_pipeline'], reducers: { @@ -158,6 +232,23 @@ export const MLInferenceLogic = kea< ...EMPTY_PIPELINE_CONFIGURATION, }, indexName: '', + simulateBody: ` +[ + { + "_index": "index", + "_id": "id", + "_source": { + "foo": "bar" + } + }, + { + "_index": "index", + "_id": "id", + "_source": { + "foo": "baz" + } + } +]`, step: AddInferencePipelineSteps.Configuration, }, { @@ -167,6 +258,10 @@ export const MLInferenceLogic = kea< ...modal, configuration, }), + setPipelineSimulateBody: (modal, { simulateBody }) => ({ + ...modal, + simulateBody, + }), }, ], createErrors: [ @@ -176,6 +271,13 @@ export const MLInferenceLogic = kea< setCreateErrors: (_, { errors }) => errors, }, ], + simulatePipelineErrors: [ + [], + { + setSimulatePipelineErrors: (_, { errors }) => errors, + simulatePipelineApiError: (_, error) => getErrorsFromHttpResponse(error), + }, + ], }, selectors: ({ selectors }) => ({ formErrors: [ @@ -217,6 +319,13 @@ export const MLInferenceLogic = kea< }); }, ], + simulatePipelineResult: [ + () => [selectors.simulatePipelineStatus, selectors.simulatePipelineData], + (status: Status, simulateResult: IngestSimulateResponse | undefined) => { + if (status !== Status.SUCCESS) return undefined; + return simulateResult; + }, + ], sourceFields: [ () => [selectors.mappingStatus, selectors.mappingData, selectors.index], ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/test_pipeline.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/test_pipeline.tsx index 523973ad2d3d1..bd5b561426cfa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/test_pipeline.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/test_pipeline.tsx @@ -7,6 +7,112 @@ import React from 'react'; +import { useValues, useActions } from 'kea'; + +import { + EuiCodeBlock, + EuiResizableContainer, + EuiButton, + EuiText, + EuiFlexGroup, + EuiFlexItem, + useIsWithinMaxBreakpoint, + EuiSpacer, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { CodeEditor } from '@kbn/kibana-react-plugin/public'; + +import { MLInferenceLogic } from './ml_inference_logic'; + +import './add_ml_inference_pipeline_modal.scss'; + export const TestPipeline: React.FC = () => { - return
      Test Pipeline
      ; + const { + addInferencePipelineModal: { simulateBody }, + simulatePipelineResult, + simulatePipelineErrors, + } = useValues(MLInferenceLogic); + const { simulatePipeline, setPipelineSimulateBody } = useActions(MLInferenceLogic); + + const isSmallerViewport = useIsWithinMaxBreakpoint('s'); + + return ( + + + +

      + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.test.title', + { defaultMessage: 'Review pipeline results (optional)' } + )} +

      +
      +
      + + + {(EuiResizablePanel, EuiResizableButton) => ( + <> + + { + setPipelineSimulateBody(value); + }} + /> + + + + + + + {simulatePipelineErrors.length > 0 + ? JSON.stringify(simulatePipelineErrors, null, 2) + : JSON.stringify(simulatePipelineResult || '', null, 2)} + + + + )} + + + + + + + +

      + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.test.description', + { + defaultMessage: + 'You can simulate your pipeline results by passing an array of documents.', + } + )} +

      +
      +
      + +
      + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.addInferencePipelineModal.steps.test.runButton', + { defaultMessage: 'Simulate Pipeline' } + )} + +
      +
      +
      +
      +
      + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx index 28e37603435e1..4c87086b5a7b6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference_pipeline_processors_card.tsx @@ -31,7 +31,7 @@ export const MlInferencePipelineProcessorsCard: React.FC = () => { return ( {inferencePipelines.map((item: InferencePipeline, index: number) => ( - + ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_model_health.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_model_health.test.tsx index 0eb88abb317e5..f6062fda4add9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_model_health.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_model_health.test.tsx @@ -24,6 +24,7 @@ describe('TrainedModelHealth', () => { }); const commonModelData: InferencePipeline = { + modelId: 'sample-bert-ner-model', modelState: TrainedModelState.NotDeployed, pipelineName: 'Sample Processor', types: ['pytorch'], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx index 4da033792a17b..0deb89a378a04 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx @@ -27,7 +27,7 @@ import { isApiIndex } from '../../../utils/indices'; import { InferenceErrors } from './inference_errors'; import { InferenceHistory } from './inference_history'; -import { IngestPipelinesCard } from './ingest_pipelines_card'; +import { IngestPipelinesCard } from './ingest_pipelines/ingest_pipelines_card'; import { AddMLInferencePipelineButton } from './ml_inference/add_ml_inference_button'; import { AddMLInferencePipelineModal } from './ml_inference/add_ml_inference_pipeline_modal'; import { MlInferencePipelineProcessorsCard } from './ml_inference_pipeline_processors_card'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts index 6cb35fed997dd..b8f6aac6f8624 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/api_logic/create_api_logic.ts @@ -44,7 +44,7 @@ export const createApiLogic = ( } }, }), - path: ['enterprise_search', ...path], + path: ['enterprise_search', 'api', ...path], reducers: () => ({ apiStatus: [ { diff --git a/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts b/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts index af11762f117d1..1f4c66e83234a 100644 --- a/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts +++ b/x-pack/plugins/enterprise_search/server/__mocks__/routerDependencies.mock.ts @@ -18,6 +18,10 @@ export const mockRequestHandler = { }, }; +export const mockMl = { + trainedModelsProvider: jest.fn(), +}; + export const mockConfig = { host: 'http://localhost:3002', accessCheckTimeout: 5000, @@ -34,4 +38,5 @@ export const mockDependencies = { config: mockConfig, log: mockLogger, enterpriseSearchRequestHandler: mockRequestHandler as any, + ml: mockMl as any, }; diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts index bb3324cf641d6..bc77b2dff7827 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.test.ts @@ -6,6 +6,7 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; +import { MlTrainedModels } from '@kbn/ml-plugin/server'; import { InferencePipeline, TrainedModelState } from '../../../common/types/pipelines'; @@ -152,7 +153,7 @@ const mockGetPipeline3 = { }; const mockGetTrainedModelsData = { - count: 1, + count: 5, trained_model_configs: [ { inference_config: { ner: {} }, @@ -172,6 +173,12 @@ const mockGetTrainedModelsData = { model_type: 'pytorch', tags: [], }, + { + inference_config: { ner: {} }, + model_id: 'trained-model-id-3-in-other-space', // Not in current Kibana space, will be filtered + model_type: 'pytorch', + tags: [], + }, { inference_config: { fill_mask: {} }, model_id: 'trained-model-id-4', @@ -206,6 +213,15 @@ const mockGetTrainedModelStats = { }, model_id: 'trained-model-id-3', }, + { + deployment_stats: { + allocation_status: { + allocation_count: 1, + }, + state: 'started', + }, + model_id: 'trained-model-id-3-in-other-space', + }, { deployment_stats: { allocation_status: { @@ -218,18 +234,29 @@ const mockGetTrainedModelStats = { ], }; +const mockTrainedModelsInCurrentSpace = { + ...mockGetTrainedModelsData, + trained_model_configs: [ + ...mockGetTrainedModelsData.trained_model_configs.slice(0, 3), // Remove 4th element + mockGetTrainedModelsData.trained_model_configs[4], + ], +}; + const trainedModelDataObject: Record = { 'trained-model-id-1': { + modelId: 'trained-model-id-1', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-1', types: ['lang_ident', 'ner'], }, 'trained-model-id-2': { + modelId: 'trained-model-id-2', modelState: TrainedModelState.Started, pipelineName: 'ml-inference-pipeline-2', types: ['pytorch', 'ner'], }, 'ml-inference-pipeline-3': { + modelId: 'trained-model-id-1', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-3', types: ['lang_ident', 'ner'], @@ -292,12 +319,14 @@ describe('fetchPipelineProcessorInferenceData lib function', () => { const expected: InferencePipelineData[] = [ { + modelId: 'trained-model-id-1', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', types: [], }, { + modelId: 'trained-model-id-2', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', @@ -324,27 +353,35 @@ describe('getMlModelConfigsForModelIds lib function', () => { getTrainedModelsStats: jest.fn(), }, }; + const mockTrainedModelsProvider = { + getTrainedModels: jest.fn(), + }; beforeEach(() => { jest.clearAllMocks(); }); - it('should fetch the models that we ask for', async () => { - mockClient.ml.getTrainedModels.mockImplementation(() => - Promise.resolve(mockGetTrainedModelsData) - ); - mockClient.ml.getTrainedModelsStats.mockImplementation(() => - Promise.resolve(mockGetTrainedModelStats) - ); + mockClient.ml.getTrainedModels.mockImplementation(() => + Promise.resolve(mockGetTrainedModelsData) + ); + mockClient.ml.getTrainedModelsStats.mockImplementation(() => + Promise.resolve(mockGetTrainedModelStats) + ); + mockTrainedModelsProvider.getTrainedModels.mockImplementation(() => + Promise.resolve(mockTrainedModelsInCurrentSpace) + ); + it('should fetch the models that we ask for', async () => { const input: Record = { 'trained-model-id-1': { + modelId: 'trained-model-id-1', modelState: TrainedModelState.Started, pipelineName: '', trainedModelName: 'trained-model-id-1', types: ['pytorch', 'ner'], }, 'trained-model-id-2': { + modelId: 'trained-model-id-2', modelState: TrainedModelState.Started, pipelineName: '', trainedModelName: 'trained-model-id-2', @@ -357,6 +394,7 @@ describe('getMlModelConfigsForModelIds lib function', () => { }; const response = await getMlModelConfigsForModelIds( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, ['trained-model-id-2'] ); expect(mockClient.ml.getTrainedModels).toHaveBeenCalledWith({ @@ -365,6 +403,51 @@ describe('getMlModelConfigsForModelIds lib function', () => { expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledWith({ model_id: 'trained-model-id-2', }); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalled(); + expect(response).toEqual(expected); + }); + + it('should redact model IDs not in the current space', async () => { + const input: Record = { + 'trained-model-id-1': { + modelId: 'trained-model-id-1', + modelState: TrainedModelState.Started, + pipelineName: '', + trainedModelName: 'trained-model-id-1', + types: ['pytorch', 'ner'], + }, + 'trained-model-id-2': { + modelId: 'trained-model-id-2', + modelState: TrainedModelState.Started, + pipelineName: '', + trainedModelName: 'trained-model-id-2', + types: ['pytorch', 'ner'], + }, + 'trained-model-id-3-in-other-space': { + modelId: undefined, // Redacted + modelState: TrainedModelState.Started, + pipelineName: '', + trainedModelName: 'trained-model-id-3-in-other-space', + types: ['pytorch', 'ner'], + }, + }; + + const expected = { + 'trained-model-id-2': input['trained-model-id-2'], + 'trained-model-id-3-in-other-space': input['trained-model-id-3-in-other-space'], + }; + const response = await getMlModelConfigsForModelIds( + mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, + ['trained-model-id-2', 'trained-model-id-3-in-other-space'] + ); + expect(mockClient.ml.getTrainedModels).toHaveBeenCalledWith({ + model_id: 'trained-model-id-2,trained-model-id-3-in-other-space', + }); + expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledWith({ + model_id: 'trained-model-id-2,trained-model-id-3-in-other-space', + }); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalled(); expect(response).toEqual(expected); }); }); @@ -376,6 +459,9 @@ describe('fetchAndAddTrainedModelData lib function', () => { getTrainedModelsStats: jest.fn(), }, }; + const mockTrainedModelsProvider = { + getTrainedModels: jest.fn(), + }; beforeEach(() => { jest.clearAllMocks(); @@ -388,27 +474,34 @@ describe('fetchAndAddTrainedModelData lib function', () => { mockClient.ml.getTrainedModelsStats.mockImplementation(() => Promise.resolve(mockGetTrainedModelStats) ); + mockTrainedModelsProvider.getTrainedModels.mockImplementation(() => + Promise.resolve(mockTrainedModelsInCurrentSpace) + ); const pipelines: InferencePipelineData[] = [ { + modelId: 'trained-model-id-1', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', types: [], }, { + modelId: 'trained-model-id-2', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', types: [], }, { + modelId: 'trained-model-id-3', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-3', trainedModelName: 'trained-model-id-3', types: [], }, { + modelId: 'trained-model-id-4', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-4', trainedModelName: 'trained-model-id-4', @@ -418,18 +511,21 @@ describe('fetchAndAddTrainedModelData lib function', () => { const expected: InferencePipelineData[] = [ { + modelId: 'trained-model-id-1', modelState: TrainedModelState.NotDeployed, pipelineName: 'ml-inference-pipeline-1', trainedModelName: 'trained-model-id-1', types: ['lang_ident', 'ner'], }, { + modelId: 'trained-model-id-2', modelState: TrainedModelState.Started, pipelineName: 'ml-inference-pipeline-2', trainedModelName: 'trained-model-id-2', types: ['pytorch', 'ner'], }, { + modelId: 'trained-model-id-3', modelState: TrainedModelState.Failed, modelStateReason: 'something is wrong, boom', pipelineName: 'ml-inference-pipeline-3', @@ -437,6 +533,7 @@ describe('fetchAndAddTrainedModelData lib function', () => { types: ['pytorch', 'text_classification'], }, { + modelId: 'trained-model-id-4', modelState: TrainedModelState.Starting, pipelineName: 'ml-inference-pipeline-4', trainedModelName: 'trained-model-id-4', @@ -446,6 +543,7 @@ describe('fetchAndAddTrainedModelData lib function', () => { const response = await fetchAndAddTrainedModelData( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, pipelines ); @@ -455,6 +553,7 @@ describe('fetchAndAddTrainedModelData lib function', () => { expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledWith({ model_id: 'trained-model-id-1,trained-model-id-2,trained-model-id-3,trained-model-id-4', }); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalled(); expect(response).toEqual(expected); }); }); @@ -469,17 +568,33 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { getTrainedModelsStats: jest.fn(), }, }; + const mockTrainedModelsProvider = { + getTrainedModels: jest.fn(), + }; beforeEach(() => { jest.clearAllMocks(); }); + describe('when Machine Learning is disabled in the current space', () => { + it('should throw an eror', () => { + expect(() => + fetchMlInferencePipelineProcessors( + mockClient as unknown as ElasticsearchClient, + undefined, + 'some-index' + ) + ).rejects.toThrowError('Machine Learning is not enabled'); + }); + }); + describe('when using an index that does not have an ml-inference pipeline', () => { it('should return an empty array', async () => { mockClient.ingest.getPipeline.mockImplementation(() => Promise.reject({})); const response = await fetchMlInferencePipelineProcessors( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, 'index-with-no-ml-inference-pipeline' ); @@ -489,6 +604,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { expect(mockClient.ingest.getPipeline).toHaveBeenCalledTimes(1); expect(mockClient.ml.getTrainedModels).toHaveBeenCalledTimes(0); expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledTimes(0); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalledTimes(0); expect(response).toEqual([]); }); @@ -505,6 +621,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { const response = await fetchMlInferencePipelineProcessors( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, 'my-index' ); @@ -533,11 +650,15 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { mockClient.ml.getTrainedModelsStats.mockImplementation(() => Promise.resolve(mockGetTrainedModelStats) ); + mockTrainedModelsProvider.getTrainedModels.mockImplementation(() => + Promise.resolve(mockTrainedModelsInCurrentSpace) + ); const expected = [trainedModelDataObject['trained-model-id-1']] as InferencePipeline[]; const response = await fetchMlInferencePipelineProcessors( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, 'my-index' ); @@ -553,6 +674,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledWith({ model_id: 'trained-model-id-1', }); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalled(); expect(response).toEqual(expected); }); @@ -580,6 +702,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { const response = await fetchMlInferencePipelineProcessors( mockClient as unknown as ElasticsearchClient, + mockTrainedModelsProvider as unknown as MlTrainedModels, 'my-index' ); @@ -595,6 +718,7 @@ describe('fetchMlInferencePipelineProcessors lib function', () => { expect(mockClient.ml.getTrainedModelsStats).toHaveBeenCalledWith({ model_id: 'trained-model-id-1', }); + expect(mockTrainedModelsProvider.getTrainedModels).toHaveBeenCalled(); expect(response).toEqual(expected); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts index 72867ad717065..e5843be2a6d7d 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/fetch_ml_inference_pipeline_processors.ts @@ -6,6 +6,7 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; +import { MlTrainedModels } from '@kbn/ml-plugin/server'; import { getMlModelTypesForModelConfig } from '../../../common/ml_inference_pipeline'; import { InferencePipeline, TrainedModelState } from '../../../common/types/pipelines'; @@ -57,6 +58,7 @@ export const fetchPipelineProcessorInferenceData = async ( const trainedModelName = inferenceProcessor?.inference?.model_id; if (trainedModelName) pipelineProcessorData.push({ + modelId: trainedModelName, modelState: TrainedModelState.NotDeployed, pipelineName: pipelineProcessorName, trainedModelName, @@ -71,20 +73,27 @@ export const fetchPipelineProcessorInferenceData = async ( export const getMlModelConfigsForModelIds = async ( client: ElasticsearchClient, + trainedModelsProvider: MlTrainedModels, trainedModelNames: string[] ): Promise> => { - const [trainedModels, trainedModelsStats] = await Promise.all([ + const [trainedModels, trainedModelsStats, trainedModelsInCurrentSpace] = await Promise.all([ client.ml.getTrainedModels({ model_id: trainedModelNames.join() }), client.ml.getTrainedModelsStats({ model_id: trainedModelNames.join() }), + trainedModelsProvider.getTrainedModels({}), // Get all models from current space; note we can't + // use exact model name matching, that returns an + // error for models that cannot be found ]); + const modelNamesInCurrentSpace = trainedModelsInCurrentSpace.trained_model_configs.map( + (modelConfig) => modelConfig.model_id + ); const modelConfigs: Record = {}; - trainedModels.trained_model_configs.forEach((trainedModelData) => { const trainedModelName = trainedModelData.model_id; if (trainedModelNames.includes(trainedModelName)) { modelConfigs[trainedModelName] = { + modelId: modelNamesInCurrentSpace.includes(trainedModelName) ? trainedModelName : undefined, modelState: TrainedModelState.NotDeployed, pipelineName: '', trainedModelName, @@ -125,21 +134,27 @@ export const getMlModelConfigsForModelIds = async ( export const fetchAndAddTrainedModelData = async ( client: ElasticsearchClient, + trainedModelsProvider: MlTrainedModels, pipelineProcessorData: InferencePipelineData[] ): Promise => { const trainedModelNames = Array.from( new Set(pipelineProcessorData.map((pipeline) => pipeline.trainedModelName)) ); - const modelConfigs = await getMlModelConfigsForModelIds(client, trainedModelNames); + const modelConfigs = await getMlModelConfigsForModelIds( + client, + trainedModelsProvider, + trainedModelNames + ); return pipelineProcessorData.map((data) => { const model = modelConfigs[data.trainedModelName]; if (!model) { return data; } - const { types, modelState, modelStateReason } = model; + const { modelId, types, modelState, modelStateReason } = model; return { ...data, + modelId, types, modelState, modelStateReason, @@ -149,8 +164,13 @@ export const fetchAndAddTrainedModelData = async ( export const fetchMlInferencePipelineProcessors = async ( client: ElasticsearchClient, + trainedModelsProvider: MlTrainedModels | undefined, indexName: string ): Promise => { + if (!trainedModelsProvider) { + return Promise.reject(new Error('Machine Learning is not enabled')); + } + const mlInferencePipelineProcessorNames = await fetchMlInferencePipelineProcessorNames( client, indexName @@ -171,7 +191,11 @@ export const fetchMlInferencePipelineProcessors = async ( // inference processors, return early to avoid fetching all of the possible trained model data. if (pipelineProcessorInferenceData.length === 0) return [] as InferencePipeline[]; - const pipelines = await fetchAndAddTrainedModelData(client, pipelineProcessorInferenceData); + const pipelines = await fetchAndAddTrainedModelData( + client, + trainedModelsProvider, + pipelineProcessorInferenceData + ); // Due to restrictions with Kibana spaces we do not want to return the trained model name // to the UI. So we remove it from the data structure here. diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 7113f09b7ffe6..90620af30f6b8 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -18,6 +18,7 @@ import { import { CustomIntegrationsPluginSetup } from '@kbn/custom-integrations-plugin/server'; import { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; import { InfraPluginSetup } from '@kbn/infra-plugin/server'; +import type { MlPluginSetup } from '@kbn/ml-plugin/server'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; @@ -70,6 +71,7 @@ interface PluginsSetup { features: FeaturesPluginSetup; infra: InfraPluginSetup; customIntegrations?: CustomIntegrationsPluginSetup; + ml?: MlPluginSetup; } interface PluginsStart { @@ -83,6 +85,7 @@ export interface RouteDependencies { log: Logger; enterpriseSearchRequestHandler: IEnterpriseSearchRequestHandler; getSavedObjectsService?(): SavedObjectsServiceStart; + ml?: MlPluginSetup; } export class EnterpriseSearchPlugin implements Plugin { @@ -96,7 +99,7 @@ export class EnterpriseSearchPlugin implements Plugin { public setup( { capabilities, http, savedObjects, getStartServices, uiSettings }: CoreSetup, - { usageCollection, security, features, infra, customIntegrations }: PluginsSetup + { usageCollection, security, features, infra, customIntegrations, ml }: PluginsSetup ) { const config = this.config; const log = this.logger; @@ -142,7 +145,7 @@ export class EnterpriseSearchPlugin implements Plugin { capabilities.registerSwitcher(async (request: KibanaRequest) => { const [, { spaces }] = await getStartServices(); - const dependencies = { config, security, spaces, request, log }; + const dependencies = { config, security, spaces, request, log, ml }; const { hasAppSearchAccess, hasWorkplaceSearchAccess } = await checkAccess(dependencies); const showEnterpriseSearch = hasAppSearchAccess || hasWorkplaceSearchAccess; @@ -172,7 +175,7 @@ export class EnterpriseSearchPlugin implements Plugin { */ const router = http.createRouter(); const enterpriseSearchRequestHandler = new EnterpriseSearchRequestHandler({ config, log }); - const dependencies = { router, config, log, enterpriseSearchRequestHandler }; + const dependencies = { router, config, log, enterpriseSearchRequestHandler, ml }; registerConfigDataRoute(dependencies); registerAppSearchRoutes(dependencies); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts index a55b67b798305..d0a652b12d9c2 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.test.ts @@ -8,6 +8,9 @@ import { MockRouter, mockDependencies } from '../../__mocks__'; import { RequestHandlerContext } from '@kbn/core/server'; +import { MlTrainedModels } from '@kbn/ml-plugin/server'; + +import { SharedServices } from '@kbn/ml-plugin/server/shared_services'; import { ErrorCode } from '../../../common/types/error_codes'; @@ -51,9 +54,9 @@ describe('Enterprise Search Managed Indices', () => { search: jest.fn(), }, }; - const mockCore = { elasticsearch: { client: mockClient }, + savedObjects: { client: {} }, }; describe('GET /internal/enterprise_search/indices/{indexName}/ml_inference/errors', () => { @@ -115,6 +118,9 @@ describe('Enterprise Search Managed Indices', () => { }); describe('GET /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors', () => { + let mockMl: SharedServices; + let mockTrainedModelsProvider: MlTrainedModels; + beforeEach(() => { const context = { core: Promise.resolve(mockCore), @@ -126,9 +132,19 @@ describe('Enterprise Search Managed Indices', () => { path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors', }); + mockTrainedModelsProvider = { + getTrainedModels: jest.fn(), + getTrainedModelsStats: jest.fn(), + } as MlTrainedModels; + + mockMl = { + trainedModelsProvider: () => Promise.resolve(mockTrainedModelsProvider), + } as unknown as jest.Mocked; + registerIndexRoutes({ ...mockDependencies, router: mockRouter.router, + ml: mockMl, }); }); @@ -157,6 +173,7 @@ describe('Enterprise Search Managed Indices', () => { expect(fetchMlInferencePipelineProcessors).toHaveBeenCalledWith( mockClient.asCurrentUser, + mockTrainedModelsProvider, 'search-index-name' ); @@ -165,6 +182,18 @@ describe('Enterprise Search Managed Indices', () => { headers: { 'content-type': 'application/json' }, }); }); + + it('returns a generic error if an error is thrown from the called service', async () => { + (fetchMlInferencePipelineProcessors as jest.Mock).mockImplementationOnce(() => { + return Promise.reject(new Error('something went wrong')); + }); + + await mockRouter.callRoute({ + params: { indexName: 'search-index-name' }, + }); + + expect(mockRouter.response.customError).toHaveBeenCalledTimes(1); + }); }); describe('POST /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors', () => { @@ -334,7 +363,7 @@ describe('Enterprise Search Managed Indices', () => { }); }); - describe('POST /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', () => { + describe('POST /internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/simulate', () => { const pipelineBody = { description: 'Some pipeline', processors: [ @@ -366,7 +395,7 @@ describe('Enterprise Search Managed Indices', () => { mockRouter = new MockRouter({ context, method: 'post', - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/simulate', }); registerIndexRoutes({ diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts index 4ae42edf16ae7..e1d2f0238740c 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts @@ -50,6 +50,7 @@ export function registerIndexRoutes({ router, enterpriseSearchRequestHandler, log, + ml, }: RouteDependencies) { router.get( { path: '/internal/enterprise_search/search_indices', validate: false }, @@ -323,10 +324,17 @@ export function registerIndexRoutes({ }, elasticsearchErrorHandler(log, async (context, request, response) => { const indexName = decodeURIComponent(request.params.indexName); - const { client } = (await context.core).elasticsearch; + const { + elasticsearch: { client }, + savedObjects: { client: savedObjectsClient }, + } = await context.core; + const trainedModelsProvider = ml + ? await ml.trainedModelsProvider(request, savedObjectsClient) + : undefined; const mlInferencePipelineProcessorConfigs = await fetchMlInferencePipelineProcessors( client.asCurrentUser, + trainedModelsProvider, indexName ); @@ -476,14 +484,14 @@ export function registerIndexRoutes({ router.post( { - path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/_simulate', + path: '/internal/enterprise_search/indices/{indexName}/ml_inference/pipeline_processors/simulate', validate: { body: schema.object({ + docs: schema.arrayOf(schema.any()), pipeline: schema.object({ description: schema.maybe(schema.string()), processors: schema.arrayOf(schema.any()), }), - docs: schema.arrayOf(schema.any()), }), params: schema.object({ indexName: schema.string(), diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index b228433c1626f..b2ccff5e7188b 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -1187,7 +1187,7 @@ "schema": { "type": "array" }, - "name": "agentsId", + "name": "agentsIds", "in": "query", "required": true } @@ -3710,7 +3710,7 @@ "/fleet_server_hosts": { "get": { "summary": "Fleet Server Hosts - List", - "description": "Return a list of Fleet server host", + "description": "Return a list of Fleet server hosts", "tags": [], "responses": { "200": { diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index f5f9dedf462d2..139711f13b899 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -735,7 +735,7 @@ paths: parameters: - schema: type: array - name: agentsId + name: agentsIds in: query required: true /agents: @@ -2292,7 +2292,7 @@ paths: /fleet_server_hosts: get: summary: Fleet Server Hosts - List - description: Return a list of Fleet server host + description: Return a list of Fleet server hosts tags: [] responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml index cde8139383065..79eed1f24fe36 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml @@ -22,6 +22,6 @@ get: parameters: - schema: type: array - name: agentsId + name: agentsIds in: query required: true diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_content.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_content.tsx index 7bf087db39eb5..2fc841d651e21 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_content.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hosts_content.tsx @@ -60,7 +60,6 @@ export const HostsContent: React.FunctionComponent = () => { {metricsDataView ? ( <> (msg: string, meta?: Meta) => {}; + +const logger = { + trace: fakeLogger, + debug: fakeLogger, + info: fakeLogger, + warn: fakeLogger, + error: fakeLogger, + fatal: fakeLogger, + log: () => void 0, + get: () => logger, +} as unknown as Logger; + const mockOptions = { alertId: '', executionId: '', @@ -99,6 +112,7 @@ const mockOptions = { ruleTypeId: '', ruleTypeName: '', }, + logger, }; const setEvaluationResults = (response: Array>) => { @@ -1607,19 +1621,6 @@ const createMockStaticConfiguration = (sources: any) => ({ sources, }); -const fakeLogger = (msg: string, meta?: Meta) => {}; - -const logger = { - trace: fakeLogger, - debug: fakeLogger, - info: fakeLogger, - warn: fakeLogger, - error: fakeLogger, - fatal: fakeLogger, - log: () => void 0, - get: () => logger, -} as unknown as Logger; - const mockLibs: any = { sources: new InfraSources({ config: createMockStaticConfiguration({}), diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx index f2b4d2b315148..2e1b021e21470 100644 --- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -927,7 +927,6 @@ export const LensTopNavMenu = ({ } textBasedLanguageModeErrors={textBasedLanguageModeErrors} onTextBasedSavedAndExit={onTextBasedSavedAndExit} - showQueryBar={true} showFilterBar={true} data-test-subj="lnsApp_topNav" screenTitle={'lens'} diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx index c05b8d415de7e..0d292b7a3a26e 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx @@ -125,7 +125,6 @@ export const countOperation: OperationDefinition + {!(isFullscreen && (autoApplyEnabled || warningMessages?.length)) && ( - + - + )} - {children} - + ); } diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 77164cfa1e1fa..103c75844f816 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -677,6 +677,7 @@ export class Embeddable renderMode={input.renderMode} syncColors={input.syncColors} syncTooltips={input.syncTooltips} + syncCursor={input.syncCursor} hasCompatibleActions={this.hasCompatibleActions} className={input.className} style={input.style} diff --git a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx index 6e2627e0e1cf6..3f10fba310b0c 100644 --- a/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx +++ b/x-pack/plugins/lens/public/embeddable/expression_wrapper.tsx @@ -39,6 +39,7 @@ export interface ExpressionWrapperProps { renderMode?: RenderMode; syncColors?: boolean; syncTooltips?: boolean; + syncCursor?: boolean; hasCompatibleActions?: ReactExpressionRendererProps['hasCompatibleActions']; style?: React.CSSProperties; className?: string; @@ -113,6 +114,7 @@ export function ExpressionWrapper({ renderMode, syncColors, syncTooltips, + syncCursor, hasCompatibleActions, style, className, @@ -143,6 +145,7 @@ export function ExpressionWrapper({ renderMode={renderMode} syncColors={syncColors} syncTooltips={syncTooltips} + syncCursor={syncCursor} executionContext={executionContext} renderError={(errorMessage, error) => { onRuntimeError(); diff --git a/x-pack/plugins/monitoring/dev_docs/how_to/local_setup.md b/x-pack/plugins/monitoring/dev_docs/how_to/local_setup.md index 2abc96a5d4957..4e1b67ddd612e 100644 --- a/x-pack/plugins/monitoring/dev_docs/how_to/local_setup.md +++ b/x-pack/plugins/monitoring/dev_docs/how_to/local_setup.md @@ -85,6 +85,13 @@ docker run --name logstash \ docker.elastic.co/logstash/logstash:master-SNAPSHOT ``` +Note that you can add these arguments to populate cgroup/cfs data for logstash as well. This will require a cgroup v1 docker host until [logstash#14534](https://github.com/elastic/logstash/issues/14534) is resolved: + +``` + --cpu-period=100000 \ + --cpu-quota=150000 \ +``` + # Complete docker setup We also maintain an internal docker-compose setup for running a full stack with monitoring enabled for all components. diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx index 41c97f41a0bc2..5c5c6a24a03d1 100644 --- a/x-pack/plugins/observability/public/application/application.test.tsx +++ b/x-pack/plugins/observability/public/application/application.test.tsx @@ -68,7 +68,12 @@ describe('renderApp', () => { const config = { unsafe: { - alertDetails: { enabled: false }, + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx index 7ad3238b4e3bf..509d8726f2ddc 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx @@ -45,7 +45,12 @@ describe('APMSection', () => { }); const config = { unsafe: { - alertDetails: { enabled: false }, + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.test.tsx b/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.test.tsx index eaa253efbc51f..20dc5caf43d70 100644 --- a/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.test.tsx @@ -71,7 +71,12 @@ const params = { const config = { unsafe: { - alertDetails: { enabled: true }, + alertDetails: { + apm: { enabled: true }, + logs: { enabled: true }, + metrics: { enabled: true }, + uptime: { enabled: true }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.tsx b/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.tsx index 1b501e62a7dde..f1515823442be 100644 --- a/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.tsx +++ b/x-pack/plugins/observability/public/pages/alert_details/components/alert_details.tsx @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { useParams } from 'react-router-dom'; import { EuiEmptyPrompt, EuiPanel } from '@elastic/eui'; +import { isAlertDetailsEnabledPerApp } from '../../../utils/is_alert_details_enabled'; import { useKibana } from '../../../utils/kibana_react'; import { usePluginContext } from '../../../hooks/use_plugin_context'; import { useBreadcrumbs } from '../../../hooks/use_breadcrumbs'; @@ -48,15 +49,15 @@ export function AlertDetails() { }, ]); - // Redirect to the the 404 page when the user hit the page url directly in the browser while the feature flag is off. - if (!config.unsafe.alertDetails.enabled) { - return ; - } - if (isLoading) { return ; } + // Redirect to the the 404 page when the user hit the page url directly in the browser while the feature flag is off. + if (alert && !isAlertDetailsEnabledPerApp(alert, config)) { + return ; + } + if (!isLoading && !alert) return ( diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_footer.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_footer.tsx index eecadba66b614..2298020c0668e 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_footer.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_footer.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { EuiFlyoutFooter, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { isAlertDetailsEnabledPerApp } from '../../../../utils/is_alert_details_enabled'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; import { FlyoutProps } from './types'; import { translations, paths } from '../../../../config'; @@ -18,7 +19,7 @@ export default function AlertsFlyoutFooter({ alert, isInApp }: FlyoutProps & { i const { http } = services; const prepend = http?.basePath.prepend; const getAlertDetailsButton = () => { - if (!config?.unsafe?.alertDetails.enabled || !alert) return <>; + if (!isAlertDetailsEnabledPerApp(alert, config)) return <>; return ( ({ const config = { unsafe: { - alertDetails: { enabled: false }, + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/public/pages/alerts/components/observability_actions.tsx b/x-pack/plugins/observability/public/pages/alerts/components/observability_actions.tsx index 2ebb4629ba7bd..8bed941ce1741 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/observability_actions.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/observability_actions.tsx @@ -19,6 +19,7 @@ import React, { useMemo, useState, useCallback } from 'react'; import { CaseAttachmentsWithoutOwner } from '@kbn/cases-plugin/public'; import { CommentType } from '@kbn/cases-plugin/common'; import type { ActionProps } from '@kbn/timelines-plugin/common'; +import { isAlertDetailsEnabledPerApp } from '../../../utils/is_alert_details_enabled'; import { useKibana } from '../../../utils/kibana_react'; import { useGetUserCasesPermissions } from '../../../hooks/use_get_user_cases_permissions'; import { parseAlert } from './parse_alert'; @@ -143,7 +144,7 @@ export function ObservabilityActions({ : []), ...[ - config?.unsafe?.alertDetails.enabled && linkToAlert ? ( + isAlertDetailsEnabledPerApp(alert, config) && linkToAlert ? ( ({ const config = { unsafe: { - alertDetails: { enabled: false }, + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 161fe2851ae3a..d6f926949ef4b 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -54,7 +54,20 @@ import getAppDataView from './utils/observability_data_views/get_app_data_view'; export interface ConfigSchema { unsafe: { - alertDetails: { enabled: boolean }; + alertDetails: { + apm: { + enabled: boolean; + }; + metrics: { + enabled: boolean; + }; + logs: { + enabled: boolean; + }; + uptime: { + enabled: boolean; + }; + }; }; } export type ObservabilityPublicSetup = ReturnType; diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts new file mode 100644 index 0000000000000..470c00d431a73 --- /dev/null +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.test.ts @@ -0,0 +1,292 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + ALERT_DURATION, + ALERT_EVALUATION_VALUE, + ALERT_INSTANCE_ID, + ALERT_RULE_NAME, + ALERT_RULE_TAGS, + ALERT_RULE_TYPE_ID, + ALERT_RULE_UUID, + ALERT_START, + ALERT_STATUS, + ALERT_UUID, + ALERT_WORKFLOW_STATUS, + EVENT_ACTION, + EVENT_KIND, + SPACE_IDS, + TIMESTAMP, + VERSION, +} from '@kbn/rule-data-utils'; +import { TopAlert } from '../pages/alerts'; +import { ConfigSchema } from '../plugin'; +import { isAlertDetailsEnabledPerApp } from './is_alert_details_enabled'; +const defaultConfig = { + unsafe: { + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, + }, +} as ConfigSchema; +describe('isAlertDetailsEnabled', () => { + describe('Logs alert', () => { + const logsAlert = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'logs.alert.document.count', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + it('returns FALSE when logs: { enabled: false }', () => { + expect(isAlertDetailsEnabledPerApp(logsAlert, defaultConfig)).toBeFalsy(); + }); + + it('returns TRUE when logs: { enabled: true }', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: false }, + logs: { enabled: true }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, + }, + } as ConfigSchema; + expect(isAlertDetailsEnabledPerApp(logsAlert, updatedConfig)).toBeTruthy(); + }); + }); + describe('APM alert', () => { + const APMAlert = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'apm.transaction_error_rate', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + it('returns FALSE when apm: { enabled: false }', () => { + expect(isAlertDetailsEnabledPerApp(APMAlert, defaultConfig)).toBeFalsy(); + }); + + it('returns TRUE when apm: { enabled: true }', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: true }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, + }, + } as ConfigSchema; + expect(isAlertDetailsEnabledPerApp(APMAlert, updatedConfig)).toBeTruthy(); + }); + }); + describe('Metrics alert', () => { + const metricsAlert = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'metrics.alert.inventory.threshold', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + it('returns FALSE when metrics: { enabled: false }', () => { + expect(isAlertDetailsEnabledPerApp(metricsAlert, defaultConfig)).toBeFalsy(); + }); + + it('returns TRUE when metrics: { enabled: true }', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: true }, + uptime: { enabled: false }, + }, + }, + } as ConfigSchema; + expect(isAlertDetailsEnabledPerApp(metricsAlert, updatedConfig)).toBeTruthy(); + }); + }); + describe('Uptime alert', () => { + const uptimeAlert = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'xpack.uptime.alerts.monitorStatus', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + it('returns FALSE when uptime: { enabled: false }', () => { + expect(isAlertDetailsEnabledPerApp(uptimeAlert, defaultConfig)).toBeFalsy(); + }); + + it('returns TRUE when uptime: { enabled: true }', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: true }, + }, + }, + } as ConfigSchema; + expect(isAlertDetailsEnabledPerApp(uptimeAlert, updatedConfig)).toBeTruthy(); + }); + }); + describe('Edge cases', () => { + it('returns FALSE when no config provided', () => { + const uptimeAlert = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'xpack.uptime.alerts.monitorStatus', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + expect(isAlertDetailsEnabledPerApp(uptimeAlert, null)).toBeFalsy(); + }); + + it('returns FALSE when no alert provided', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: true }, + logs: { enabled: true }, + metrics: { enabled: true }, + uptime: { enabled: true }, + }, + }, + } as ConfigSchema; + expect(isAlertDetailsEnabledPerApp(undefined, updatedConfig)).toBeFalsy(); + }); + it('returns FALSE when a none-listed rule type is checked', () => { + const updatedConfig = { + unsafe: { + alertDetails: { + apm: { enabled: true }, + logs: { enabled: true }, + metrics: { enabled: true }, + uptime: { enabled: true }, + }, + }, + } as ConfigSchema; + const noneListedRuleType = { + reason: 'reason message', + fields: { + [ALERT_STATUS]: 'active', + [TIMESTAMP]: '2022-09-02T13:08:51.750Z', + [ALERT_DURATION]: 882076000, + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_UUID]: 'db2ab7c0-0bec-11ec-9ae2-5b10ca924404', + [ALERT_START]: '2021-09-02T12:54:09.674Z', + [ALERT_RULE_TYPE_ID]: 'new.rule.type.not.listed', + [EVENT_ACTION]: 'active', + [ALERT_EVALUATION_VALUE]: 1957, + [ALERT_INSTANCE_ID]: '*', + [ALERT_RULE_NAME]: 'mockedRule', + [ALERT_UUID]: '432ab7c0-0bec-11ec-9ae2-4b10ca857438', + [SPACE_IDS]: ['default'], + [VERSION]: '8.0.0', + [EVENT_KIND]: 'signal', + [ALERT_RULE_TAGS]: [], + }, + active: true, + start: 1630587249674, + lastUpdated: 1630588131750, + } as unknown as TopAlert; + expect(isAlertDetailsEnabledPerApp(noneListedRuleType, updatedConfig)).toBeFalsy(); + }); + }); +}); diff --git a/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts new file mode 100644 index 0000000000000..c9e928814a0a3 --- /dev/null +++ b/x-pack/plugins/observability/public/utils/is_alert_details_enabled.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ALERT_RULE_TYPE_ID } from '@kbn/rule-data-utils'; +import { TopAlert } from '../pages/alerts'; +import { ConfigSchema } from '../plugin'; + +// We are mapping the ruleTypeId from the feature flag with the ruleTypeId form the alert +// to know whether the feature flag is enabled or not. +export const isAlertDetailsEnabledPerApp = ( + alert?: TopAlert | null, + config?: ConfigSchema | null +): boolean => { + if (!alert || !config) return false; + const ruleTypeIdFromFeatureFlag = Object.keys(config.unsafe.alertDetails); + let ruleTypeId = alert.fields[ALERT_RULE_TYPE_ID].split('.')[0] as string; + + // Uptime rule type id is not following the same name convention as all the other rules, so dedicated treatment needed. + if (alert.fields[ALERT_RULE_TYPE_ID] === 'xpack.uptime.alerts.monitorStatus') + ruleTypeId = 'uptime'; + + const appName = ruleTypeId as unknown as keyof ConfigSchema['unsafe']['alertDetails']; + return ( + ruleTypeIdFromFeatureFlag.includes(ruleTypeId) && config?.unsafe?.alertDetails[appName].enabled + ); +}; diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index 3b43312ee263d..0a184290fab4e 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -29,7 +29,12 @@ const observabilityRuleTypeRegistry = createObservabilityRuleTypeRegistryMock(); const defaultConfig = { unsafe: { - alertDetails: { enabled: false }, + alertDetails: { + apm: { enabled: false }, + logs: { enabled: false }, + metrics: { enabled: false }, + uptime: { enabled: false }, + }, }, } as ConfigSchema; diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index dad8d5a36bd33..e8b6582a9184e 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -32,7 +32,18 @@ const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), }), alertDetails: schema.object({ - enabled: schema.boolean({ defaultValue: false }), + apm: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), + metrics: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), + logs: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), + uptime: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), }), }), }); diff --git a/x-pack/plugins/profiling/public/components/profiling_app_page_template/profiling_search_bar.tsx b/x-pack/plugins/profiling/public/components/profiling_app_page_template/profiling_search_bar.tsx index de20f0f3211e0..210bb66be4067 100644 --- a/x-pack/plugins/profiling/public/components/profiling_app_page_template/profiling_search_bar.tsx +++ b/x-pack/plugins/profiling/public/components/profiling_app_page_template/profiling_search_bar.tsx @@ -64,7 +64,6 @@ export function ProfilingSearchBar({ onQuerySubmit({ dateRange, query }); }} - showQueryBar showQueryInput showDatePicker showFilterBar={false} diff --git a/x-pack/plugins/profiling/server/routes/stacktrace.ts b/x-pack/plugins/profiling/server/routes/stacktrace.ts index aee9b61694e21..0f513023fa829 100644 --- a/x-pack/plugins/profiling/server/routes/stacktrace.ts +++ b/x-pack/plugins/profiling/server/routes/stacktrace.ts @@ -6,7 +6,6 @@ */ import type { Logger } from '@kbn/core/server'; -import { chunk } from 'lodash'; import LRUCache from 'lru-cache'; import { INDEX_EXECUTABLES, INDEX_FRAMES, INDEX_TRACES } from '../../common'; import { @@ -32,8 +31,6 @@ import { withProfilingSpan } from '../utils/with_profiling_span'; import { DownsampledEventsIndex } from './downsampling'; import { ProjectTimeQuery } from './query'; -const traceLRU = new LRUCache({ max: 20000 }); - const BASE64_FRAME_ID_LENGTH = 32; export type EncodedStackTrace = DedotObject<{ @@ -236,80 +233,102 @@ export async function searchEventsGroupByStackTrace({ return { totalCount, stackTraceEvents }; } +function summarizeCacheAndQuery( + logger: Logger, + name: string, + cacheHits: number, + cacheTotal: number, + queryHits: number, + queryTotal: number +) { + logger.info(`found ${cacheHits} out of ${cacheTotal} ${name} in the cache`); + if (cacheHits === cacheTotal) { + return; + } + logger.info(`found ${queryHits} out of ${queryTotal} ${name}`); + if (queryHits < queryTotal) { + logger.info(`failed to find ${queryTotal - queryHits} ${name}`); + } +} + +const traceLRU = new LRUCache({ max: 20000 }); + export async function mgetStackTraces({ logger, client, events, - concurrency = 1, }: { logger: Logger; client: ProfilingESClient; events: Map; - concurrency?: number; }) { - const stackTraceIDs = [...events.keys()]; - const chunkSize = Math.floor(events.size / concurrency); - let chunks = chunk(stackTraceIDs, chunkSize); - - if (chunks.length !== concurrency) { - // The last array element contains the remainder, just drop it as irrelevant. - chunks = chunks.slice(0, concurrency); - } - - const stackResponses = await withProfilingSpan('mget_stacktraces', () => - Promise.all( - chunks.map((ids) => { - return client.mget< - PickFlattened< - ProfilingStackTrace, - ProfilingESField.StacktraceFrameIDs | ProfilingESField.StacktraceFrameTypes - > - >('mget_stacktraces_chunk', { - index: INDEX_TRACES, - ids, - realtime: true, - _source_includes: [ - ProfilingESField.StacktraceFrameIDs, - ProfilingESField.StacktraceFrameTypes, - ], - }); - }) - ) - ); + const stackTraceIDs = new Set([...events.keys()]); + const stackTraces = new Map(); + let cacheHits = 0; let totalFrames = 0; - const stackTraces = new Map(); const stackFrameDocIDs = new Set(); const executableDocIDs = new Set(); + for (const stackTraceID of stackTraceIDs) { + const stackTrace = traceLRU.get(stackTraceID); + if (stackTrace) { + cacheHits++; + stackTraceIDs.delete(stackTraceID); + stackTraces.set(stackTraceID, stackTrace); + + totalFrames += stackTrace.FrameIDs.length; + for (const frameID of stackTrace.FrameIDs) { + stackFrameDocIDs.add(frameID); + } + for (const fileID of stackTrace.FileIDs) { + executableDocIDs.add(fileID); + } + } + } + + if (stackTraceIDs.size === 0) { + summarizeCacheAndQuery(logger, 'stacktraces', cacheHits, events.size, 0, 0); + return { stackTraces, totalFrames, stackFrameDocIDs, executableDocIDs }; + } + + const stackResponses = await client.mget< + PickFlattened< + ProfilingStackTrace, + ProfilingESField.StacktraceFrameIDs | ProfilingESField.StacktraceFrameTypes + > + >('mget_stacktraces', { + index: INDEX_TRACES, + ids: [...stackTraceIDs], + realtime: true, + _source_includes: [ProfilingESField.StacktraceFrameIDs, ProfilingESField.StacktraceFrameTypes], + }); + + let queryHits = 0; const t0 = Date.now(); await withProfilingSpan('decode_stacktraces', async () => { - // flatMap() is significantly slower than an explicit for loop - for (const res of stackResponses) { - for (const trace of res.docs) { - if ('error' in trace) { - continue; + for (const trace of stackResponses.docs) { + if ('error' in trace) { + continue; + } + // Sometimes we don't find the trace. + // This is due to ES delays writing (data is not immediately seen after write). + // Also, ES doesn't know about transactions. + if (trace.found) { + queryHits++; + const traceid = trace._id as StackTraceID; + const stackTrace = decodeStackTrace(trace._source as EncodedStackTrace); + + stackTraces.set(traceid, stackTrace); + traceLRU.set(traceid, stackTrace); + + totalFrames += stackTrace.FrameIDs.length; + for (const frameID of stackTrace.FrameIDs) { + stackFrameDocIDs.add(frameID); } - // Sometimes we don't find the trace. - // This is due to ES delays writing (data is not immediately seen after write). - // Also, ES doesn't know about transactions. - if (trace.found) { - const traceid = trace._id as StackTraceID; - let stackTrace = traceLRU.get(traceid) as StackTrace; - if (!stackTrace) { - stackTrace = decodeStackTrace(trace._source as EncodedStackTrace); - traceLRU.set(traceid, stackTrace); - } - - totalFrames += stackTrace.FrameIDs.length; - stackTraces.set(traceid, stackTrace); - for (const frameID of stackTrace.FrameIDs) { - stackFrameDocIDs.add(frameID); - } - for (const fileID of stackTrace.FileIDs) { - executableDocIDs.add(fileID); - } + for (const fileID of stackTrace.FileIDs) { + executableDocIDs.add(fileID); } } } @@ -321,15 +340,20 @@ export async function mgetStackTraces({ logger.info('Average size of stacktrace: ' + totalFrames / stackTraces.size); } - if (stackTraces.size < events.size) { - logger.info( - 'failed to find ' + (events.size - stackTraces.size) + ' stacktraces (todo: find out why)' - ); - } + summarizeCacheAndQuery( + logger, + 'stacktraces', + cacheHits, + events.size, + queryHits, + stackTraceIDs.size + ); return { stackTraces, totalFrames, stackFrameDocIDs, executableDocIDs }; } +const frameLRU = new LRUCache({ max: 100000 }); + export async function mgetStackFrames({ logger, client, @@ -341,7 +365,20 @@ export async function mgetStackFrames({ }): Promise> { const stackFrames = new Map(); + let cacheHits = 0; + const cacheTotal = stackFrameIDs.size; + + for (const stackFrameID of stackFrameIDs) { + const stackFrame = frameLRU.get(stackFrameID); + if (stackFrame) { + cacheHits++; + stackFrames.set(stackFrameID, stackFrame); + stackFrameIDs.delete(stackFrameID); + } + } + if (stackFrameIDs.size === 0) { + summarizeCacheAndQuery(logger, 'frames', cacheHits, cacheTotal, 0, 0); return stackFrames; } @@ -352,7 +389,7 @@ export async function mgetStackFrames({ }); // Create a lookup map StackFrameID -> StackFrame. - let framesFound = 0; + let queryHits = 0; const t0 = Date.now(); const docs = resStackFrames.docs; for (const frame of docs) { @@ -360,25 +397,32 @@ export async function mgetStackFrames({ continue; } if (frame.found) { - stackFrames.set(frame._id, { + queryHits++; + const stackFrame = { FileName: frame._source!.Stackframe.file?.name, FunctionName: frame._source!.Stackframe.function?.name, FunctionOffset: frame._source!.Stackframe.function?.offset, LineNumber: frame._source!.Stackframe.line?.number, SourceType: frame._source!.Stackframe.source?.type, - }); - framesFound++; - } else { - stackFrames.set(frame._id, emptyStackFrame); + }; + stackFrames.set(frame._id, stackFrame); + frameLRU.set(frame._id, stackFrame); + continue; } + + stackFrames.set(frame._id, emptyStackFrame); + frameLRU.set(frame._id, emptyStackFrame); } + logger.info(`processing data took ${Date.now() - t0} ms`); - logger.info('found ' + framesFound + ' / ' + stackFrameIDs.size + ' frames'); + summarizeCacheAndQuery(logger, 'frames', cacheHits, cacheTotal, queryHits, stackFrameIDs.size); return stackFrames; } +const executableLRU = new LRUCache({ max: 100000 }); + export async function mgetExecutables({ logger, client, @@ -390,7 +434,20 @@ export async function mgetExecutables({ }): Promise> { const executables = new Map(); + let cacheHits = 0; + const cacheTotal = executableIDs.size; + + for (const fileID of executableIDs) { + const executable = executableLRU.get(fileID); + if (executable) { + cacheHits++; + executables.set(fileID, executable); + executableIDs.delete(fileID); + } + } + if (executableIDs.size === 0) { + summarizeCacheAndQuery(logger, 'frames', cacheHits, cacheTotal, 0, 0); return executables; } @@ -400,8 +457,8 @@ export async function mgetExecutables({ _source_includes: [ProfilingESField.ExecutableFileName], }); - // Create a lookup map StackFrameID -> StackFrame. - let exeFound = 0; + // Create a lookup map FileID -> Executable. + let queryHits = 0; const t0 = Date.now(); const docs = resExecutables.docs; for (const exe of docs) { @@ -409,17 +466,29 @@ export async function mgetExecutables({ continue; } if (exe.found) { - executables.set(exe._id, { + queryHits++; + const executable = { FileName: exe._source!.Executable.file.name, - }); - exeFound++; - } else { - executables.set(exe._id, emptyExecutable); + }; + executables.set(exe._id, executable); + executableLRU.set(exe._id, executable); + continue; } + + executables.set(exe._id, emptyExecutable); + executableLRU.set(exe._id, emptyExecutable); } + logger.info(`processing data took ${Date.now() - t0} ms`); - logger.info('found ' + exeFound + ' / ' + executableIDs.size + ' executables'); + summarizeCacheAndQuery( + logger, + 'executables', + cacheHits, + cacheTotal, + queryHits, + executableIDs.size + ); return executables; } diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts index f0190ef7adf67..b4aa184cab592 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts @@ -49,6 +49,7 @@ describe('createLifecycleExecutor', () => { createDefaultAlertExecutorOptions({ params: {}, state: { wrapped: initialRuleState, trackedAlerts: {} }, + logger, }) ); @@ -83,6 +84,7 @@ describe('createLifecycleExecutor', () => { createDefaultAlertExecutorOptions({ params: {}, state: { wrapped: initialRuleState, trackedAlerts: {} }, + logger, }) ); @@ -198,6 +200,7 @@ describe('createLifecycleExecutor', () => { }, }, }, + logger, }) ); @@ -313,6 +316,7 @@ describe('createLifecycleExecutor', () => { }, }, }, + logger, }) ); @@ -372,6 +376,7 @@ describe('createLifecycleExecutor', () => { params: {}, state: { wrapped: initialRuleState, trackedAlerts: {} }, shouldWriteAlerts: false, + logger, }) ); @@ -401,6 +406,7 @@ describe('createLifecycleExecutor', () => { params: {}, state: { wrapped: initialRuleState, trackedAlerts: {} }, shouldWriteAlerts: false, + logger, }) ) ).rejects.toThrowErrorMatchingInlineSnapshot(`"error initializing!"`); diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts index acb12645cbaed..f71c7391cec77 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_rule_type.test.ts @@ -131,6 +131,7 @@ function createRule(shouldWriteAlerts: boolean = true) { updatedBy: 'updatedBy', namespace: 'namespace', executionId: 'b33f65d7-6e8b-4aae-8d20-c93613dec9f9', + logger: loggerMock.create(), })) ?? {}) as Record; previousStartedAt = startedAt; diff --git a/x-pack/plugins/rule_registry/server/utils/rule_executor.test_helpers.ts b/x-pack/plugins/rule_registry/server/utils/rule_executor.test_helpers.ts index b2c25973f7cc4..4a9ab6652ec6e 100644 --- a/x-pack/plugins/rule_registry/server/utils/rule_executor.test_helpers.ts +++ b/x-pack/plugins/rule_registry/server/utils/rule_executor.test_helpers.ts @@ -18,6 +18,7 @@ import { } from '@kbn/alerting-plugin/server'; import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { searchSourceCommonMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { Logger } from '@kbn/logging'; export const createDefaultAlertExecutorOptions = < Params extends RuleTypeParams = never, @@ -30,6 +31,7 @@ export const createDefaultAlertExecutorOptions = < ruleName = 'ALERT_RULE_NAME', params, state, + logger, createdAt = new Date(), startedAt = new Date(), updatedAt = new Date(), @@ -39,6 +41,7 @@ export const createDefaultAlertExecutorOptions = < ruleName?: string; params: Params; state: State; + logger: Logger; createdAt?: Date; startedAt?: Date; updatedAt?: Date; @@ -83,4 +86,5 @@ export const createDefaultAlertExecutorOptions = < previousStartedAt: null, namespace: undefined, executionId: 'b33f65d7-6e8b-4aae-8d20-c93613deb33f', + logger, }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/timelines/unsaved_timeline.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/unsaved_timeline.cy.ts index e18937ee1fc09..93eab97a503de 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/timelines/unsaved_timeline.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/timelines/unsaved_timeline.cy.ts @@ -31,7 +31,7 @@ import { populateTimeline, waitForTimelineChanges, } from '../../tasks/timeline'; -import { HOSTS_URL } from '../../urls/navigation'; +import { HOSTS_URL, MANAGE_URL } from '../../urls/navigation'; describe('Save Timeline Prompts', () => { before(() => { @@ -129,7 +129,7 @@ describe('Save Timeline Prompts', () => { cy.url().should('not.contain', HOSTS_URL); }); - it('When user navigates to the page where timeline is present, Time save modal shold not exists.', () => { + it('When user navigates to the page where timeline is present, Time save modal should not exists.', () => { populateTimeline(); waitForTimelineChanges(); closeTimelineUsingToggle(); @@ -145,4 +145,22 @@ describe('Save Timeline Prompts', () => { cy.get(ALERTS_PAGE).click(); cy.get(TIMELINE_SAVE_MODAL).should('not.exist'); }); + + it('Changed and unsaved timeline should NOT prompt when user navigates from the page where timeline is disabled', () => { + populateTimeline(); + waitForTimelineChanges(); + closeTimelineUsingToggle(); + openKibanaNavigation(); + cy.get(MANAGE_PAGE).click(); + cy.get(APP_LEAVE_CONFIRM_MODAL).should('be.visible'); + cy.get(MODAL_CONFIRMATION_BTN).click(); + // now we have come from MANAGE_PAGE where timeline is disabled + // to outside app where timeline is not present. + // There should be NO confirmation model in that case. + openKibanaNavigation(); + navigateFromKibanaCollapsibleTo(OBSERVABILITY_ALERTS_PAGE); + // should not be manage page i.e. successfull navigation + cy.get(TIMELINE_SAVE_MODAL).should('not.exist'); + cy.url().should('not.contain', MANAGE_URL); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/filter_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/filter_bar/index.tsx index 9150882a9b37d..e960ef8e99f7d 100644 --- a/x-pack/plugins/security_solution/public/common/components/filter_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/filter_bar/index.tsx @@ -59,7 +59,6 @@ export const FilterBar = memo( showAutoRefreshOnly={false} showFilterBar={true} showDatePicker={false} - showQueryBar={false} showQueryInput={false} showSaveQuery={false} dataTestSubj={dataTestSubj} diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx index b9e95a2ee837e..118c78e290759 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx @@ -202,7 +202,6 @@ describe('QueryBar ', () => { showAutoRefreshOnly: false, showDatePicker: false, showFilterBar: true, - showQueryBar: true, showQueryInput: true, showSaveQuery: true, showSubmitButton: false, diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx index 82080ba1ac602..d86f3de10b549 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.tsx @@ -125,7 +125,6 @@ export const QueryBar = memo( showAutoRefreshOnly={false} showFilterBar={!hideSavedQuery} showDatePicker={false} - showQueryBar={true} showQueryInput={true} showSaveQuery={true} timeHistory={timeHistory} diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index 188c7a1359743..ba7efafb6b0dd 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -311,7 +311,6 @@ export const SearchBarComponent = memo( savedQuery={savedQuery} showFilterBar={!hideFilterBar} showDatePicker={true} - showQueryBar={true} showQueryInput={!hideQueryInput} showSaveQuery={true} dataTestSubj={dataTestSubj} diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/use_pick_index_patterns.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/use_pick_index_patterns.tsx index fd704f175a852..7be02be6abc37 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/use_pick_index_patterns.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/use_pick_index_patterns.tsx @@ -195,11 +195,7 @@ export const usePickIndexPatterns = ({ // constantly getting destroy and re-init const pickedDataViewData = await getSourcererDataView(newSelectedDataViewId); if (isHookAlive.current) { - dispatch( - sourcererActions.updateSourcererDataViews({ - dataView: pickedDataViewData, - }) - ); + dispatch(sourcererActions.setDataView(pickedDataViewData)); setSelectedOptions( isOnlyDetectionAlerts ? alertsOptions diff --git a/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx b/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx index c259f8843263a..a5dd7f10edaab 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx @@ -33,6 +33,7 @@ export type IndexFieldSearch = (param: { scopeId?: SourcererScopeName; needToBeInit?: boolean; cleanCache?: boolean; + skipScopeUpdate?: boolean; }) => Promise; type DangerCastForBrowserFieldsMutation = Record< @@ -102,6 +103,7 @@ export const useDataView = (): { scopeId = SourcererScopeName.default, needToBeInit = false, cleanCache = false, + skipScopeUpdate = false, }) => { const unsubscribe = () => { searchSubscription$.current[dataViewId]?.unsubscribe(); @@ -123,11 +125,7 @@ export const useDataView = (): { dataViewId, abortCtrl.current[dataViewId].signal ); - dispatch( - sourcererActions.updateSourcererDataViews({ - dataView: dataViewToUpdate, - }) - ); + dispatch(sourcererActions.setDataView(dataViewToUpdate)); } return new Promise((resolve) => { @@ -148,7 +146,7 @@ export const useDataView = (): { endTracking('success'); const patternString = response.indicesExist.sort().join(); - if (needToBeInit && scopeId) { + if (needToBeInit && scopeId && !skipScopeUpdate) { dispatch( sourcererActions.setSelectedDataView({ id: scopeId, diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx index 9be9c1266c1c9..634330ea10e91 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx @@ -34,6 +34,7 @@ import { import type { SelectedDataView } from '../../store/sourcerer/model'; import { SourcererScopeName } from '../../store/sourcerer/model'; import { postSourcererDataView } from './api'; +import * as source from '../source/use_data_view'; import { sourcererActions } from '../../store/sourcerer'; import { useInitializeUrlParam, useUpdateUrlParam } from '../../utils/global_query_string'; @@ -200,7 +201,7 @@ describe('Sourcerer Hooks', () => { }); }); - it('initilizes dataview with data from query string', async () => { + it('initializes dataview with data from query string', async () => { const selectedPatterns = ['testPattern-*']; const selectedDataViewId = 'security-solution-default'; (useInitializeUrlParam as jest.Mock).mockImplementation((_, onInitialize) => @@ -342,6 +343,198 @@ describe('Sourcerer Hooks', () => { }); }); }); + describe('initialization settings', () => { + const mockIndexFieldsSearch = jest.fn(); + beforeAll(() => { + // 👇️ not using dot-notation + the ignore clears up a ts error + // @ts-ignore + // eslint-disable-next-line dot-notation + source['useDataView'] = jest.fn(() => ({ + indexFieldsSearch: mockIndexFieldsSearch, + })); + }); + it('does not needToBeInit if scope is default and selectedPatterns/missingPatterns have values', async () => { + await act(async () => { + const { rerender, waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ + dataViewId: mockSourcererState.defaultDataView.id, + needToBeInit: false, + scopeId: SourcererScopeName.default, + }); + }); + }); + }); + + it('does needToBeInit if scope is default and selectedPatterns/missingPatterns are empty', async () => { + store = createStore( + { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.default]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], + selectedPatterns: [], + missingPatterns: [], + }, + }, + }, + }, + SUB_PLUGINS_REDUCER, + kibanaObservable, + storage + ); + await act(async () => { + const { rerender, waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenCalledWith({ + dataViewId: mockSourcererState.defaultDataView.id, + needToBeInit: true, + scopeId: SourcererScopeName.default, + }); + }); + }); + }); + + it('does needToBeInit and skipScopeUpdate=false if scope is timeline and selectedPatterns/missingPatterns are empty', async () => { + store = createStore( + { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + kibanaDataViews: [ + ...mockGlobalState.sourcerer.kibanaDataViews, + { ...mockSourcererState.defaultDataView, id: 'something-weird', patternList: [] }, + ], + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.timeline]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline], + selectedDataViewId: 'something-weird', + selectedPatterns: [], + missingPatterns: [], + }, + }, + }, + }, + SUB_PLUGINS_REDUCER, + kibanaObservable, + storage + ); + await act(async () => { + const { rerender, waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: true, + scopeId: SourcererScopeName.timeline, + skipScopeUpdate: false, + }); + }); + }); + }); + + it('does needToBeInit and skipScopeUpdate=true if scope is timeline and selectedPatterns have value', async () => { + store = createStore( + { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + kibanaDataViews: [ + ...mockGlobalState.sourcerer.kibanaDataViews, + { ...mockSourcererState.defaultDataView, id: 'something-weird', patternList: [] }, + ], + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.timeline]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline], + selectedDataViewId: 'something-weird', + selectedPatterns: ['ohboy'], + missingPatterns: [], + }, + }, + }, + }, + SUB_PLUGINS_REDUCER, + kibanaObservable, + storage + ); + await act(async () => { + const { rerender, waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: true, + scopeId: SourcererScopeName.timeline, + skipScopeUpdate: true, + }); + }); + }); + }); + + it('does not needToBeInit if scope is timeline and data view has patternList', async () => { + store = createStore( + { + ...mockGlobalState, + sourcerer: { + ...mockGlobalState.sourcerer, + kibanaDataViews: [ + ...mockGlobalState.sourcerer.kibanaDataViews, + { + ...mockSourcererState.defaultDataView, + id: 'something-weird', + patternList: ['ohboy'], + }, + ], + sourcererScopes: { + ...mockGlobalState.sourcerer.sourcererScopes, + [SourcererScopeName.timeline]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.timeline], + selectedDataViewId: 'something-weird', + selectedPatterns: [], + missingPatterns: [], + }, + }, + }, + }, + SUB_PLUGINS_REDUCER, + kibanaObservable, + storage + ); + await act(async () => { + const { rerender, waitForNextUpdate } = renderHook(() => useInitSourcerer(), { + wrapper: ({ children }) => {children}, + }); + await waitForNextUpdate(); + rerender(); + await waitFor(() => { + expect(mockIndexFieldsSearch).toHaveBeenNthCalledWith(2, { + dataViewId: 'something-weird', + needToBeInit: false, + scopeId: SourcererScopeName.timeline, + }); + }); + }); + }); + }); describe('useSourcererDataView', () => { it('Should put any excludes in the index pattern at the end of the pattern list, and sort both the includes and excludes', async () => { diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx index 6db7392b596b7..07dafff7470d7 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.tsx @@ -76,17 +76,21 @@ export const useInitSourcerer = ( const activeTimeline = useDeepEqualSelector((state) => getTimelineSelector(state, TimelineId.active) ); - const scopeIdSelector = useMemo(() => sourcererSelectors.scopeIdSelector(), []); + + const sourcererScopeSelector = useMemo(() => sourcererSelectors.getSourcererScopeSelector(), []); const { - selectedDataViewId: scopeDataViewId, - selectedPatterns, - missingPatterns, - } = useDeepEqualSelector((state) => scopeIdSelector(state, scopeId)); + sourcererScope: { selectedDataViewId: scopeDataViewId, selectedPatterns, missingPatterns }, + } = useDeepEqualSelector((state) => sourcererScopeSelector(state, scopeId)); + const { - selectedDataViewId: timelineDataViewId, - selectedPatterns: timelineSelectedPatterns, - missingPatterns: timelineMissingPatterns, - } = useDeepEqualSelector((state) => scopeIdSelector(state, SourcererScopeName.timeline)); + selectedDataView: timelineSelectedDataView, + sourcererScope: { + selectedDataViewId: timelineDataViewId, + selectedPatterns: timelineSelectedPatterns, + missingPatterns: timelineMissingPatterns, + }, + } = useDeepEqualSelector((state) => sourcererScopeSelector(state, SourcererScopeName.timeline)); + const { indexFieldsSearch } = useDataView(); const onInitializeUrlParam = useCallback( @@ -137,19 +141,29 @@ export const useInitSourcerer = ( const searchedIds = useRef([]); useEffect(() => { const activeDataViewIds = [...new Set([scopeDataViewId, timelineDataViewId])]; - activeDataViewIds.forEach((id) => { + activeDataViewIds.forEach((id, i) => { if (id != null && id.length > 0 && !searchedIds.current.includes(id)) { searchedIds.current = [...searchedIds.current, id]; + + const currentScope = i === 0 ? SourcererScopeName.default : SourcererScopeName.timeline; + + const needToBeInit = + id === scopeDataViewId + ? selectedPatterns.length === 0 && missingPatterns.length === 0 + : timelineDataViewId === id + ? timelineMissingPatterns.length === 0 && + timelineSelectedDataView?.patternList.length === 0 + : false; + indexFieldsSearch({ dataViewId: id, - scopeId: - id === scopeDataViewId ? SourcererScopeName.default : SourcererScopeName.timeline, - needToBeInit: - id === scopeDataViewId - ? selectedPatterns.length === 0 && missingPatterns.length === 0 - : timelineDataViewId === id - ? timelineMissingPatterns.length === 0 && timelineSelectedPatterns.length === 0 - : false, + scopeId: currentScope, + needToBeInit, + ...(needToBeInit && currentScope === SourcererScopeName.timeline + ? { + skipScopeUpdate: timelineSelectedPatterns.length > 0, + } + : {}), }); } }); @@ -160,6 +174,7 @@ export const useInitSourcerer = ( selectedPatterns.length, timelineDataViewId, timelineMissingPatterns.length, + timelineSelectedDataView, timelineSelectedPatterns.length, ]); diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_does_endpoint_support_responder.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_does_endpoint_support_responder.ts index f98020fe62d7f..27158cbfad831 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_does_endpoint_support_responder.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_does_endpoint_support_responder.ts @@ -12,9 +12,12 @@ export const useDoesEndpointSupportResponder = ( endpointMetadata: MaybeImmutable | undefined ): boolean => { if (endpointMetadata) { - return ENDPOINT_CAPABILITIES.every((capability) => - endpointMetadata?.Endpoint.capabilities?.includes(capability) - ); + return ENDPOINT_CAPABILITIES.every((capability) => { + // TODO: remove this temporary bypass when in-context Response Console capabilities are enabled + const temporaryBypass = capability === 'get_file'; + + return endpointMetadata?.Endpoint.capabilities?.includes(capability) || temporaryBypass; + }); } return false; }; diff --git a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts index 84c37a58fcf4f..72337661c6c38 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts @@ -117,5 +117,11 @@ export const useTimelineSavePrompt = ( return actions.default(); } }); + + return () => { + // removing app leave handler for timeline when + // components containing timeline unmounts + onAppLeave((actions) => actions.default()); + }; }); }; diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts index f452d34cba310..db6dcedef8262 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/actions.ts @@ -7,23 +7,12 @@ import actionCreatorFactory from 'typescript-fsa'; -import type { - KibanaDataView, - SelectedDataView, - SourcererDataView, - SourcererScopeName, -} from './model'; +import type { SelectedDataView, SourcererDataView, SourcererScopeName } from './model'; import type { SecurityDataView } from '../../containers/sourcerer/api'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/sourcerer'); -export const setDataView = actionCreator<{ - browserFields: SourcererDataView['browserFields']; - id: SourcererDataView['id']; - indexFields: SourcererDataView['indexFields']; - loading: SourcererDataView['loading']; - runtimeMappings: SourcererDataView['runtimeMappings']; -}>('SET_DATA_VIEW'); +export const setDataView = actionCreator>('SET_DATA_VIEW'); export const setDataViewLoading = actionCreator<{ id: string; @@ -48,7 +37,3 @@ export interface SelectedDataViewPayload { shouldValidateSelectedPatterns?: boolean; } export const setSelectedDataView = actionCreator('SET_SELECTED_DATA_VIEW'); - -export const updateSourcererDataViews = actionCreator<{ - dataView: KibanaDataView; -}>('UPDATE_SOURCERER_DATA_VIEWS'); diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts index a1b9586834cf6..aa193026465cf 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { mockGlobalState } from '../../mock'; +import { mockGlobalState, mockSourcererState } from '../../mock'; import { SourcererScopeName } from './model'; import { getScopePatternListSelection, validateSelectedPatterns } from './helpers'; import { sortWithExcludesAtEnd } from '../../../../common/utils/sourcerer'; @@ -210,5 +210,71 @@ describe('sourcerer store helpers', () => { }); }); }); + + it('does not attempt to validate when missing patterns', () => { + const state = { + ...mockGlobalState.sourcerer, + defaultDataView: { + ...mockSourcererState.defaultDataView, + patternList: [], + }, + kibanaDataViews: [ + { + ...mockSourcererState.defaultDataView, + patternList: [], + }, + ], + }; + const result = validateSelectedPatterns( + state, + { + ...payload, + id: SourcererScopeName.default, + selectedPatterns: ['auditbeat-*', 'yoohoo'], + }, + true + ); + expect(result).toEqual({ + [SourcererScopeName.default]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], + missingPatterns: ['yoohoo'], + selectedPatterns: ['auditbeat-*', 'yoohoo'], + }, + }); + }); + + it('does not attempt to validate if non-default data view has not been initialized', () => { + const state = { + ...mockGlobalState.sourcerer, + defaultDataView: { + ...mockSourcererState.defaultDataView, + patternList: [], + }, + kibanaDataViews: [ + { + ...mockSourcererState.defaultDataView, + id: 'wow', + patternList: [], + }, + ], + }; + const result = validateSelectedPatterns( + state, + { + ...payload, + id: SourcererScopeName.default, + selectedDataViewId: 'wow', + selectedPatterns: ['auditbeat-*', 'yoohoo'], + }, + true + ); + expect(result).toEqual({ + [SourcererScopeName.default]: { + ...mockGlobalState.sourcerer.sourcererScopes[SourcererScopeName.default], + selectedDataViewId: 'wow', + selectedPatterns: ['auditbeat-*', 'yoohoo'], + }, + }); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts index 187e4923ed218..3d3b061194f79 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/helpers.ts @@ -58,7 +58,12 @@ export const validateSelectedPatterns = ( const selectedPatterns = // shouldValidateSelectedPatterns is false when upgrading from // legacy pre-8.0 timeline index patterns to data view. - shouldValidateSelectedPatterns && dataView != null && missingPatterns.length === 0 + shouldValidateSelectedPatterns && + dataView != null && + missingPatterns.length === 0 && + // don't validate when the data view has not been initialized (default is initialized already always) + dataView.id !== state.defaultDataView.id && + dataView.patternList.length > 0 ? dedupePatterns.filter( (pattern) => (dataView != null && dataView.patternList.includes(pattern)) || diff --git a/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts index dc084956bcad8..5a253083d8b15 100644 --- a/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts +++ b/x-pack/plugins/security_solution/public/common/store/sourcerer/reducer.ts @@ -14,7 +14,6 @@ import { setSignalIndexName, setDataView, setDataViewLoading, - updateSourcererDataViews, } from './actions'; import type { SourcererModel } from './model'; import { initDataView, initialSourcererState, SourcererScopeName } from './model'; @@ -47,12 +46,6 @@ export const sourcererReducer = reducerWithInitialState(initialSourcererState) ...dataView, })), })) - .case(updateSourcererDataViews, (state, { dataView }) => ({ - ...state, - kibanaDataViews: state.kibanaDataViews.map((dv) => - dv.id === dataView.id ? { ...dv, ...dataView } : dv - ), - })) .case(setSourcererScopeLoading, (state, { id, loading }) => ({ ...state, sourcererScopes: { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.tsx index c2fef59ebd460..8b7f668df439d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.tsx @@ -63,7 +63,6 @@ export const AdminSearchBar = memo(() => { iconType="search" showFilterBar={false} showDatePicker={false} - showQueryBar={true} showQueryInput={true} />

      diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts index 664abac92db93..17d1d8f9a9295 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts @@ -19,6 +19,7 @@ import { import { buildManifestManagerMock } from '../endpoint/services/artifacts/manifest_manager/manifest_manager.mock'; import { getPackagePolicyCreateCallback, + getPackagePolicyPostCreateCallback, getPackagePolicyDeleteCallback, getPackagePolicyUpdateCallback, } from './fleet_integration'; @@ -40,11 +41,16 @@ import type { InternalArtifactCompleteSchema } from '../endpoint/schemas/artifac import { ManifestManager } from '../endpoint/services/artifacts/manifest_manager'; import { getMockArtifacts, toArtifactRecords } from '../endpoint/lib/artifacts/mocks'; import { Manifest } from '../endpoint/lib/artifacts'; -import type { NewPackagePolicy } from '@kbn/fleet-plugin/common/types/models'; +import type { NewPackagePolicy, PackagePolicy } from '@kbn/fleet-plugin/common/types/models'; import type { ManifestSchema } from '../../common/endpoint/schema/manifest'; import type { DeletePackagePoliciesResponse } from '@kbn/fleet-plugin/common'; import { createMockPolicyData } from '../endpoint/services/feature_usage/mocks'; import { ALL_ENDPOINT_ARTIFACT_LIST_IDS } from '../../common/endpoint/service/artifacts/constants'; +import { ENDPOINT_EVENT_FILTERS_LIST_ID } from '@kbn/securitysolution-list-constants'; + +jest.mock('uuid', () => ({ + v4: (): string => 'NEW_UUID', +})); describe('ingest_integration tests ', () => { let endpointAppContextMock: EndpointAppContextServiceStartContract; @@ -248,12 +254,75 @@ describe('ingest_integration tests ', () => { expect(manifestManager.pushArtifacts).not.toHaveBeenCalled(); expect(manifestManager.commit).not.toHaveBeenCalled(); }); - - it.todo('should override policy config with endpoint settings'); - it.todo('should override policy config with cloud settings'); }); + describe('package policy post create callback', () => { - it.todo('should create Event Filters given valid parameter on integration config'); + const logger = loggingSystemMock.create().get('ingest_integration.test'); + const callback = getPackagePolicyPostCreateCallback(logger, exceptionListClient); + const policyConfig = generator.generatePolicyPackagePolicy() as PackagePolicy; + + it('should create the Endpoint Event Filters List and add the correct Event Filters List Item attached to the policy given nonInteractiveSession parameter on integration config eventFilters', async () => { + const integrationConfig = { + type: 'cloud', + eventFilters: { + nonInteractiveSession: true, + }, + }; + + policyConfig.inputs[0]!.config!.integration_config = { + value: integrationConfig, + }; + const postCreatedPolicyConfig = await callback( + policyConfig, + requestContextMock.convertContext(ctx), + req + ); + + expect(await exceptionListClient.createExceptionList).toHaveBeenCalledWith( + expect.objectContaining({ listId: ENDPOINT_EVENT_FILTERS_LIST_ID }) + ); + + expect(await exceptionListClient.createExceptionListItem).toHaveBeenCalledWith( + expect.objectContaining({ + listId: ENDPOINT_EVENT_FILTERS_LIST_ID, + tags: [`policy:${postCreatedPolicyConfig.id}`], + osTypes: ['linux'], + entries: [ + { + field: 'process.entry_leader.interactive', + operator: 'included', + type: 'match', + value: 'false', + }, + ], + itemId: 'NEW_UUID', + namespaceType: 'agnostic', + }) + ); + }); + + it('should not call Event Filters List and Event Filters List Item if nonInteractiveSession parameter is not present on integration config eventFilters', async () => { + const integrationConfig = { + type: 'cloud', + }; + + policyConfig.inputs[0]!.config!.integration_config = { + value: integrationConfig, + }; + const postCreatedPolicyConfig = await callback( + policyConfig, + requestContextMock.convertContext(ctx), + req + ); + + expect(await exceptionListClient.createExceptionList).not.toHaveBeenCalled(); + + expect(await exceptionListClient.createExceptionListItem).not.toHaveBeenCalled(); + + expect(postCreatedPolicyConfig.inputs[0]!.config!.integration_config.value).toEqual( + integrationConfig + ); + }); }); describe('package policy update callback (when the license is below platinum)', () => { beforeEach(() => { diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts new file mode 100644 index 0000000000000..73440a310b625 --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { Subject } from 'rxjs'; +import type { ILicense } from '@kbn/licensing-plugin/common/types'; +import { licenseMock } from '@kbn/licensing-plugin/common/licensing.mock'; +import { LicenseService } from '../../../common/license'; +import { createDefaultPolicy } from './create_default_policy'; +import type { PolicyConfig } from '../../../common/endpoint/types'; +import { + policyFactory as policyConfigFactory, + policyFactoryWithoutPaidFeatures as policyConfigFactoryWithoutPaidFeatures, +} from '../../../common/endpoint/models/policy_config'; +import type { + AnyPolicyCreateConfig, + PolicyCreateCloudConfig, + PolicyCreateEndpointConfig, +} from '../types'; + +describe('Create Default Policy tests ', () => { + const Platinum = licenseMock.createLicense({ license: { type: 'platinum', mode: 'platinum' } }); + const Gold = licenseMock.createLicense({ license: { type: 'gold', mode: 'gold' } }); + let licenseEmitter: Subject; + let licenseService: LicenseService; + + const createDefaultPolicyCallback = (config: AnyPolicyCreateConfig | undefined): PolicyConfig => { + return createDefaultPolicy(licenseService, config); + }; + + beforeEach(() => { + licenseEmitter = new Subject(); + licenseService = new LicenseService(); + licenseService.start(licenseEmitter); + licenseEmitter.next(Platinum); // set license level to platinum + }); + describe('When no config is set', () => { + it('Should return the Default Policy Config when license is at least platinum', () => { + const policy = createDefaultPolicyCallback(undefined); + expect(policy).toEqual(policyConfigFactory()); + }); + it('Should return the Default Policy Config without paid features when license is below platinum', () => { + licenseEmitter.next(Gold); + const policy = createDefaultPolicyCallback(undefined); + expect(policy).toEqual(policyConfigFactoryWithoutPaidFeatures()); + }); + }); + describe('When endpoint config is set', () => { + const createEndpointConfig = ( + endpointConfig: PolicyCreateEndpointConfig['endpointConfig'] + ): PolicyCreateEndpointConfig => { + return { + type: 'endpoint', + endpointConfig, + }; + }; + + const defaultEventsDisabled = () => ({ + linux: { + process: false, + file: false, + network: false, + session_data: false, + tty_io: false, + }, + mac: { + process: false, + file: false, + network: false, + }, + windows: { + process: false, + file: false, + network: false, + dll_and_driver_load: false, + dns: false, + registry: false, + security: false, + }, + }); + const OSTypes = ['linux', 'mac', 'windows'] as const; + + it('Should return only process event enabled on policy when preset is NGAV', () => { + const config = createEndpointConfig({ preset: 'NGAV' }); + const policy = createDefaultPolicyCallback(config); + const events = defaultEventsDisabled(); + OSTypes.forEach((os) => { + expect(policy[os].events).toMatchObject({ + ...events[os], + process: true, + }); + }); + }); + it('Should return process, file and network events enabled when preset is EDR Essential', () => { + const config = createEndpointConfig({ preset: 'EDREssential' }); + const policy = createDefaultPolicyCallback(config); + const events = defaultEventsDisabled(); + const enabledEvents = { + process: true, + file: true, + network: true, + }; + OSTypes.forEach((os) => { + expect(policy[os].events).toMatchObject({ + ...events[os], + ...enabledEvents, + }); + }); + }); + it('Should return the default config when preset is EDR Complete', () => { + const config = createEndpointConfig({ preset: 'EDRComplete' }); + const policy = createDefaultPolicyCallback(config); + const policyFactory = policyConfigFactory(); + expect(policy).toMatchObject(policyFactory); + }); + }); + describe('When cloud config is set', () => { + const createCloudConfig = (): PolicyCreateCloudConfig => ({ + type: 'cloud', + }); + + it('Session data should be enabled for Linux', () => { + const config = createCloudConfig(); + const policy = createDefaultPolicyCallback(config); + expect(policy.linux.events.session_data).toBe(true); + }); + it('Protections should be disabled for all OSs', () => { + const config = createCloudConfig(); + const policy = createDefaultPolicyCallback(config); + const OSTypes = ['linux', 'mac', 'windows'] as const; + OSTypes.forEach((os) => { + expect(policy[os].malware.mode).toBe('off'); + expect(policy[os].memory_protection.mode).toBe('off'); + expect(policy[os].behavior_protection.mode).toBe('off'); + }); + // Ransomware is windows only + expect(policy.windows.ransomware.mode).toBe('off'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts index 89d760c4e6eeb..b79e8ac4cbbdb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_rules_notification_alert_type.test.ts @@ -70,6 +70,7 @@ describe('legacyRules_notification_alert_type', () => { throttle: null, notifyWhen: null, }, + logger, }; alert = legacyRulesNotificationAlertType({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts index 15b6ffe47d349..9a1ba3a2b144c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import uuid from 'uuid'; import { transformError } from '@kbn/securitysolution-es-utils'; -import type { StartServicesAccessor } from '@kbn/core/server'; +import type { Logger, StartServicesAccessor } from '@kbn/core/server'; import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import type { AlertInstanceContext, @@ -64,7 +64,8 @@ export const previewRulesRoute = async ( ruleOptions: CreateRuleOptions, securityRuleTypeOptions: CreateSecurityRuleTypeWrapperProps, previewRuleDataClient: IRuleDataClient, - getStartServices: StartServicesAccessor + getStartServices: StartServicesAccessor, + logger: Logger ) => { router.post( { @@ -251,6 +252,7 @@ export const previewRulesRoute = async ( state: statePreview, tags: [], updatedBy: rule.updatedBy, + logger, })) as TState; const errors = loggedStatusChanges diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts index 96ca9e9d5ef40..bfe25804de29a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/rule_type.ts @@ -114,6 +114,7 @@ export const createRuleTypeMocks = ( params, alertId: v4(), state: {}, + logger: loggerMock, }), runOpts: { completeRule: getCompleteRuleMock(params as QueryRuleParams), diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index 485047721ab18..f9d2177aa9e10 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -118,7 +118,8 @@ export const initRoutes = ( ruleOptions, securityRuleTypeOptions, previewRuleDataClient, - getStartServices + getStartServices, + logger ); createRuleExceptionsRoute(router); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx index 67526a53a6b8e..6274a4dcdba95 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx @@ -259,7 +259,6 @@ export const SearchSourceExpressionForm = (props: SearchSourceExpressionFormProp onSavedQueryUpdated={onSavedQuery} onSaved={onSavedQuery} showSaveQuery - showQueryBar showQueryInput showFilterBar showDatePicker={false} diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/executor.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/executor.ts index b52f5803405a7..f50368f29ae76 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/executor.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/executor.ts @@ -6,7 +6,7 @@ */ import { sha256 } from 'js-sha256'; import { i18n } from '@kbn/i18n'; -import { CoreSetup, Logger } from '@kbn/core/server'; +import { CoreSetup } from '@kbn/core/server'; import { parseDuration } from '@kbn/alerting-plugin/server'; import { addMessages, EsQueryRuleActionContext } from './action_context'; import { ComparatorFns, getHumanReadableComparator } from '../lib'; @@ -18,13 +18,9 @@ import { fetchSearchSourceQuery } from './lib/fetch_search_source_query'; import { Comparator } from '../../../common/comparator_types'; import { isEsQueryRule } from './util'; -export async function executor( - logger: Logger, - core: CoreSetup, - options: ExecutorOptions -) { +export async function executor(core: CoreSetup, options: ExecutorOptions) { const esQueryRule = isEsQueryRule(options.params.searchType); - const { alertId: ruleId, name, services, params, state, spaceId } = options; + const { alertId: ruleId, name, services, params, state, spaceId, logger } = options; const { alertFactory, scopedClusterClient, searchSourceClient } = services; const currentTimestamp = new Date().toISOString(); const publicBaseUrl = core.http.basePath.publicBaseUrl ?? ''; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/index.ts index 54bfabdf49ad6..a92b5be3a9d63 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/index.ts @@ -5,17 +5,16 @@ * 2.0. */ -import { CoreSetup, Logger } from '@kbn/core/server'; +import { CoreSetup } from '@kbn/core/server'; import { AlertingSetup } from '../../types'; import { getRuleType } from './rule_type'; interface RegisterParams { - logger: Logger; alerting: AlertingSetup; core: CoreSetup; } export function register(params: RegisterParams) { - const { logger, alerting, core } = params; - alerting.registerType(getRuleType(logger, core)); + const { alerting, core } = params; + alerting.registerType(getRuleType(core)); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts index 18397e4515e7b..b647531222407 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts @@ -27,7 +27,7 @@ import { Comparator } from '../../../common/comparator_types'; const logger = loggingSystemMock.create().get(); const coreSetup = coreMock.createSetup(); -const ruleType = getRuleType(logger, coreSetup); +const ruleType = getRuleType(coreSetup); describe('ruleType', () => { it('rule type creation structure is the expected value', async () => { @@ -678,5 +678,6 @@ async function invokeExecutor({ throttle: null, notifyWhen: null, }, + logger, }); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.ts index 27e79e86fb3c3..c56f691cc2580 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, Logger } from '@kbn/core/server'; +import { CoreSetup } from '@kbn/core/server'; import { extractReferences, injectReferences } from '@kbn/data-plugin/common'; import { RuleType } from '../../types'; import { ActionContext } from './action_context'; @@ -23,7 +23,6 @@ import { executor } from './executor'; import { isEsQueryRule } from './util'; export function getRuleType( - logger: Logger, core: CoreSetup ): RuleType< EsQueryRuleParams, @@ -184,7 +183,7 @@ export function getRuleType( minimumLicenseRequired: 'basic', isExportable: true, executor: async (options: ExecutorOptions) => { - return await executor(logger, core, options); + return await executor(core, options); }, producer: STACK_ALERTS_FEATURE_ID, doesSetRecoveryContext: true, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts index 95e7376a6febb..4a0c89531c880 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/alert_type.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; -import { Logger, SavedObjectReference } from '@kbn/core/server'; +import { SavedObjectReference } from '@kbn/core/server'; import { RuleType, RuleTypeState, @@ -214,7 +214,7 @@ export function injectEntityAndBoundaryIds( } as GeoContainmentParams; } -export function getAlertType(logger: Logger): GeoContainmentAlertType { +export function getAlertType(): GeoContainmentAlertType { const alertTypeName = i18n.translate('xpack.stackAlerts.geoContainment.alertTypeTitle', { defaultMessage: 'Tracking containment', }); @@ -238,7 +238,7 @@ export function getAlertType(logger: Logger): GeoContainmentAlertType { }, doesSetRecoveryContext: true, defaultActionGroupId: ActionGroupId, - executor: getGeoContainmentExecutor(logger), + executor: getGeoContainmentExecutor(), producer: STACK_ALERTS_FEATURE_ID, validate: { params: ParamsSchema, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts index efa8c869ed405..fd86dc3d3800d 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts @@ -6,7 +6,6 @@ */ import _ from 'lodash'; -import { Logger } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RuleExecutorServices } from '@kbn/alerting-plugin/server'; import { executeEsQueryFactory, getShapesFilters, OTHER_CATEGORY } from './es_query_builder'; @@ -138,7 +137,7 @@ export function getEntitiesAndGenerateAlerts( return { activeEntities, inactiveEntities }; } -export const getGeoContainmentExecutor = (log: Logger): GeoContainmentAlertType['executor'] => +export const getGeoContainmentExecutor = (): GeoContainmentAlertType['executor'] => async function ({ previousStartedAt: windowStart, startedAt: windowEnd, @@ -146,6 +145,7 @@ export const getGeoContainmentExecutor = (log: Logger): GeoContainmentAlertType[ params, alertId, state, + logger, }): Promise { const { shapesFilters, shapesIdsNamesMap } = state.shapesFilters ? state @@ -154,7 +154,7 @@ export const getGeoContainmentExecutor = (log: Logger): GeoContainmentAlertType[ params.boundaryGeoField, params.geoField, services.scopedClusterClient.asCurrentUser, - log, + logger, alertId, params.boundaryNameField, params.boundaryIndexQuery @@ -163,14 +163,14 @@ export const getGeoContainmentExecutor = (log: Logger): GeoContainmentAlertType[ const executeEsQuery = await executeEsQueryFactory( params, services.scopedClusterClient.asCurrentUser, - log, + logger, shapesFilters ); // Start collecting data only on the first cycle let currentIntervalResults: estypes.SearchResponse | undefined; if (!windowStart) { - log.debug(`alert ${GEO_CONTAINMENT_ID}:${alertId} alert initialized. Collecting data`); + logger.debug(`alert ${GEO_CONTAINMENT_ID}:${alertId} alert initialized. Collecting data`); // Consider making first time window configurable? const START_TIME_WINDOW = 1; const tempPreviousEndTime = new Date(windowEnd); @@ -213,7 +213,7 @@ export const getGeoContainmentExecutor = (log: Logger): GeoContainmentAlertType[ recoveredAlert.setContext(context); } } catch (e) { - log.warn(`Unable to set alert context for recovered alert, error: ${e.message}`); + logger.warn(`Unable to set alert context for recovered alert, error: ${e.message}`); } } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts index 072a01efc9749..f5b9ebc5e85cd 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { Logger } from '@kbn/core/server'; import { AlertingSetup } from '../../types'; import { GeoContainmentState, @@ -19,12 +18,11 @@ import { import { GeoContainmentExtractedParams, GeoContainmentParams } from './alert_type'; interface RegisterParams { - logger: Logger; alerting: AlertingSetup; } export function register(params: RegisterParams) { - const { logger, alerting } = params; + const { alerting } = params; alerting.registerType< GeoContainmentParams, GeoContainmentExtractedParams, @@ -33,5 +31,5 @@ export function register(params: RegisterParams) { GeoContainmentInstanceContext, typeof ActionGroupId, typeof RecoveryActionGroupId - >(getAlertType(logger)); + >(getAlertType()); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts index 1f08564a4d668..9a67a1280f730 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/alert_type.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { loggingSystemMock } from '@kbn/core/server/mocks'; import { getAlertType, injectEntityAndBoundaryIds, @@ -14,9 +13,7 @@ import { } from '../alert_type'; describe('alertType', () => { - const logger = loggingSystemMock.create().get(); - - const alertType = getAlertType(logger); + const alertType = getAlertType(); it('alert type creation structure is the expected value', async () => { expect(alertType.id).toBe('.geo-containment'); diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/geo_containment.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/geo_containment.test.ts index 82dac9ba6ff9a..e4d4e49036f4e 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/geo_containment.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/tests/geo_containment.test.ts @@ -6,7 +6,7 @@ */ import _ from 'lodash'; -import { loggingSystemMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { RuleExecutorServicesMock, alertsMock } from '@kbn/alerting-plugin/server/mocks'; import sampleAggsJsonResponse from './es_sample_response.json'; import sampleShapesJsonResponse from './es_sample_response_shapes.json'; @@ -505,7 +505,6 @@ describe('geo_containment', () => { }, ]; const testAlertActionArr: unknown[] = []; - const mockLogger = loggingSystemMock.createLogger(); const previousStartedAt = new Date('2021-04-27T16:56:11.923Z'); const startedAt = new Date('2021-04-29T16:56:11.923Z'); const geoContainmentParams: GeoContainmentParams = { @@ -560,7 +559,7 @@ describe('geo_containment', () => { }); it('should query for shapes if state does not contain shapes', async () => { - const executor = await getGeoContainmentExecutor(mockLogger); + const executor = await getGeoContainmentExecutor(); // @ts-ignore const executionResult = await executor({ previousStartedAt, @@ -580,7 +579,7 @@ describe('geo_containment', () => { }); it('should not query for shapes if state contains shapes', async () => { - const executor = await getGeoContainmentExecutor(mockLogger); + const executor = await getGeoContainmentExecutor(); // @ts-ignore const executionResult = await executor({ previousStartedAt, @@ -599,7 +598,7 @@ describe('geo_containment', () => { }); it('should carry through shapes filters in state to next call unmodified', async () => { - const executor = await getGeoContainmentExecutor(mockLogger); + const executor = await getGeoContainmentExecutor(); // @ts-ignore const executionResult = await executor({ previousStartedAt, @@ -635,7 +634,7 @@ describe('geo_containment', () => { }, ], }; - const executor = await getGeoContainmentExecutor(mockLogger); + const executor = await getGeoContainmentExecutor(); // @ts-ignore const executionResult = await executor({ previousStartedAt, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts index 449c6528798a6..dbae7907dd9f6 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { Logger } from '@kbn/core/server'; import { AlertingSetup, StackAlertsStartDeps } from '../../types'; import { getRuleType } from './rule_type'; @@ -15,12 +14,11 @@ export const MAX_GROUPS = 1000; export const DEFAULT_GROUPS = 100; interface RegisterParams { - logger: Logger; data: Promise; alerting: AlertingSetup; } export function register(params: RegisterParams) { - const { logger, data, alerting } = params; - alerting.registerType(getRuleType(logger, data)); + const { data, alerting } = params; + alerting.registerType(getRuleType(data)); } diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.test.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.test.ts index adb722ef094d2..f7704e4699930 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.test.ts @@ -26,7 +26,7 @@ describe('ruleType', () => { }; const alertServices: RuleExecutorServicesMock = alertsMock.createRuleExecutorServices(); - const ruleType = getRuleType(logger, Promise.resolve(data)); + const ruleType = getRuleType(Promise.resolve(data)); beforeAll(() => { fakeTimer = sinon.useFakeTimers(); @@ -220,6 +220,7 @@ describe('ruleType', () => { throttle: null, notifyWhen: null, }, + logger, }); expect(alertServices.alertFactory.create).toHaveBeenCalledWith('all documents'); @@ -286,6 +287,7 @@ describe('ruleType', () => { throttle: null, notifyWhen: null, }, + logger, }); expect(customAlertServices.alertFactory.create).not.toHaveBeenCalled(); @@ -352,6 +354,7 @@ describe('ruleType', () => { throttle: null, notifyWhen: null, }, + logger, }); expect(customAlertServices.alertFactory.create).not.toHaveBeenCalled(); @@ -417,6 +420,7 @@ describe('ruleType', () => { throttle: null, notifyWhen: null, }, + logger, }); expect(data.timeSeriesQuery).toHaveBeenCalledWith( diff --git a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.ts index 32f30c2db437d..2fcb36b267d6d 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/index_threshold/rule_type.ts @@ -6,7 +6,6 @@ */ import { i18n } from '@kbn/i18n'; -import { Logger } from '@kbn/core/server'; import { CoreQueryParamsSchemaProperties, TimeSeriesQuery, @@ -23,7 +22,6 @@ export const ID = '.index-threshold'; export const ActionGroupId = 'threshold met'; export function getRuleType( - logger: Logger, data: Promise ): RuleType { const ruleTypeName = i18n.translate('xpack.stackAlerts.indexThreshold.alertTypeTitle', { @@ -136,7 +134,7 @@ export function getRuleType( async function executor( options: RuleExecutorOptions ) { - const { alertId: ruleId, name, services, params } = options; + const { alertId: ruleId, name, services, params, logger } = options; const { alertFactory, scopedClusterClient } = services; const alertLimit = alertFactory.alertLimit.getValue(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/cases_webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/cases_webhook/index.ts index 3b32e79ac725c..9bfb66f1a69aa 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/cases_webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/cases_webhook/index.ts @@ -5,8 +5,6 @@ * 2.0. */ -import { curry } from 'lodash'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -35,11 +33,7 @@ const supportedSubActions: string[] = ['pushToService']; export type ActionParamsType = CasesWebhookActionParamsType; export const ConnectorTypeId = '.cases-webhook'; // connector type definition -export function getConnectorType({ - logger, -}: { - logger: Logger; -}): ConnectorType< +export function getConnectorType(): ConnectorType< CasesWebhookPublicConfigurationType, CasesWebhookSecretConfigurationType, ExecutorParams, @@ -63,23 +57,21 @@ export function getConnectorType({ }, connector: validate.connector, }, - executor: curry(executor)({ logger }), + executor, supportedFeatureIds: [CasesConnectorFeatureId], }; } // action executor export async function executor( - { logger }: { logger: Logger }, execOptions: ConnectorTypeExecutorOptions< CasesWebhookPublicConfigurationType, CasesWebhookSecretConfigurationType, CasesWebhookActionParamsType > ): Promise> { - const actionId = execOptions.actionId; - const configurationUtilities = execOptions.configurationUtilities; - const { subAction, subActionParams } = execOptions.params; + const { actionId, configurationUtilities, params, logger } = execOptions; + const { subAction, subActionParams } = params; let data: CasesWebhookExecutorResultData | undefined; const externalService = createExternalService( diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/jira/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/jira/index.ts index d2130c085cda1..630c0973935cd 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/jira/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/jira/index.ts @@ -5,10 +5,8 @@ * 2.0. */ -import { curry } from 'lodash'; import { TypeOf } from '@kbn/config-schema'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -43,9 +41,6 @@ import { import * as i18n from './translations'; export type ActionParamsType = TypeOf; -interface GetConnectorTypeParams { - logger: Logger; -} const supportedSubActions: string[] = [ 'getFields', @@ -59,15 +54,12 @@ const supportedSubActions: string[] = [ export const ConnectorTypeId = '.jira'; // connector type definition -export function getConnectorType( - params: GetConnectorTypeParams -): ConnectorType< +export function getConnectorType(): ConnectorType< JiraPublicConfigurationType, JiraSecretConfigurationType, ExecutorParams, JiraExecutorResultData | {} > { - const { logger } = params; return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -91,20 +83,19 @@ export function getConnectorType( schema: ExecutorParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, }; } // action executor async function executor( - { logger }: { logger: Logger }, execOptions: ConnectorTypeExecutorOptions< JiraPublicConfigurationType, JiraSecretConfigurationType, ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: JiraExecutorResultData | null = null; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/resilient/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/resilient/index.ts index 081fbe92502d9..7ef85b84bfb86 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/resilient/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/resilient/index.ts @@ -5,10 +5,8 @@ * 2.0. */ -import { curry } from 'lodash'; import { TypeOf } from '@kbn/config-schema'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -41,23 +39,16 @@ import * as i18n from './translations'; export type ActionParamsType = TypeOf; -interface GetConnectorTypeParams { - logger: Logger; -} - const supportedSubActions: string[] = ['getFields', 'pushToService', 'incidentTypes', 'severity']; export const ConnectorTypeId = '.resilient'; // connector type definition -export function getConnectorType( - params: GetConnectorTypeParams -): ConnectorType< +export function getConnectorType(): ConnectorType< ResilientPublicConfigurationType, ResilientSecretConfigurationType, ExecutorParams, ResilientExecutorResultData | {} > { - const { logger } = params; return { id: ConnectorTypeId, minimumLicenseRequired: 'platinum', @@ -80,20 +71,19 @@ export function getConnectorType( schema: ExecutorParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, }; } // action executor async function executor( - { logger }: { logger: Logger }, execOptions: ConnectorTypeExecutorOptions< ResilientPublicConfigurationType, ResilientSecretConfigurationType, ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: ResilientExecutorResultData | null = null; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.test.ts index 50ff4d8e0f1c9..422098e146945 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.test.ts @@ -49,9 +49,7 @@ describe('ServiceNow', () => { describe('ServiceNow ITSM', () => { let connectorType: ServiceNowConnectorType; beforeAll(() => { - connectorType = getServiceNowITSMConnectorType({ - logger: mockedLogger, - }); + connectorType = getServiceNowITSMConnectorType(); }); describe('execute()', () => { @@ -67,6 +65,7 @@ describe('ServiceNow', () => { secrets, params, services, + logger: mockedLogger, } as unknown as ServiceNowConnectorTypeExecutorOptions< ServiceNowPublicConfigurationType, ExecutorParams diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.ts index 40e9d1470950e..39cba22889ae2 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_itsm/index.ts @@ -8,7 +8,6 @@ import { curry } from 'lodash'; import { TypeOf } from '@kbn/config-schema'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -55,10 +54,6 @@ export { ServiceNowITSMConnectorTypeId, serviceNowITSMTable }; export type ActionParamsType = TypeOf; -interface GetConnectorTypeParams { - logger: Logger; -} - export type ServiceNowConnectorType< C extends Record = ServiceNowPublicConfigurationBaseType, T extends Record = ExecutorParams @@ -70,10 +65,10 @@ export type ServiceNowConnectorTypeExecutorOptions< > = ConnectorTypeExecutorOptions; // connector type definition -export function getServiceNowITSMConnectorType( - params: GetConnectorTypeParams -): ServiceNowConnectorType { - const { logger } = params; +export function getServiceNowITSMConnectorType(): ServiceNowConnectorType< + ServiceNowPublicConfigurationType, + ExecutorParams +> { return { id: ServiceNowITSMConnectorTypeId, minimumLicenseRequired: 'platinum', @@ -99,7 +94,6 @@ export function getServiceNowITSMConnectorType( }, }, executor: curry(executor)({ - logger, actionTypeId: ServiceNowITSMConnectorTypeId, createService: createExternalService, api: apiITSM, @@ -111,12 +105,10 @@ export function getServiceNowITSMConnectorType( const supportedSubActions: string[] = ['getFields', 'pushToService', 'getChoices', 'getIncident']; async function executor( { - logger, actionTypeId, createService, api, }: { - logger: Logger; actionTypeId: string; createService: ServiceFactory; api: ExternalServiceAPI; @@ -126,7 +118,8 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, services, configurationUtilities, logger } = + execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.test.ts index 3fff7ae0e389d..2389852334ef8 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.test.ts @@ -50,9 +50,7 @@ describe('ServiceNow', () => { let connectorType: ServiceNowConnectorType; beforeAll(() => { - connectorType = getServiceNowSIRConnectorType({ - logger: mockedLogger, - }); + connectorType = getServiceNowSIRConnectorType(); }); describe('execute()', () => { @@ -68,6 +66,7 @@ describe('ServiceNow', () => { secrets, params, services, + logger: mockedLogger, } as unknown as ServiceNowConnectorTypeExecutorOptions< ServiceNowPublicConfigurationType, ExecutorParams diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.ts index 16db999af8a1e..8f5cb9a86286d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/servicenow_sir/index.ts @@ -8,7 +8,6 @@ import { curry } from 'lodash'; import { TypeOf } from '@kbn/config-schema'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -54,10 +53,6 @@ export { ServiceNowSIRConnectorTypeId, serviceNowSIRTable }; export type ActionParamsType = TypeOf; -interface GetConnectorTypeParams { - logger: Logger; -} - export type ServiceNowConnectorType< C extends Record = ServiceNowPublicConfigurationBaseType, T extends Record = ExecutorParams @@ -69,10 +64,10 @@ export type ServiceNowConnectorTypeExecutorOptions< > = ConnectorTypeExecutorOptions; // connector type definition -export function getServiceNowSIRConnectorType( - params: GetConnectorTypeParams -): ServiceNowConnectorType { - const { logger } = params; +export function getServiceNowSIRConnectorType(): ServiceNowConnectorType< + ServiceNowPublicConfigurationType, + ExecutorParams +> { return { id: ServiceNowSIRConnectorTypeId, minimumLicenseRequired: 'platinum', @@ -97,7 +92,6 @@ export function getServiceNowSIRConnectorType( }, }, executor: curry(executor)({ - logger, actionTypeId: ServiceNowSIRConnectorTypeId, createService: createExternalService, api: apiSIR, @@ -109,12 +103,10 @@ export function getServiceNowSIRConnectorType( const supportedSubActions: string[] = ['getFields', 'pushToService', 'getChoices', 'getIncident']; async function executor( { - logger, actionTypeId, createService, api, }: { - logger: Logger; actionTypeId: string; createService: ServiceFactory; api: ExternalServiceAPI; @@ -124,7 +116,8 @@ async function executor( ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, services, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, services, configurationUtilities, logger } = + execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases/swimlane/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases/swimlane/index.ts index a033abd875ea4..d24febcccaad3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases/swimlane/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases/swimlane/index.ts @@ -5,9 +5,7 @@ * 2.0. */ -import { curry } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { Logger } from '@kbn/logging'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -34,23 +32,15 @@ import { import { createExternalService } from './service'; import { api } from './api'; -interface GetConnectorTypeParams { - logger: Logger; -} - const supportedSubActions: string[] = ['pushToService']; // connector type definition -export function getConnectorType( - params: GetConnectorTypeParams -): ConnectorType< +export function getConnectorType(): ConnectorType< SwimlanePublicConfigurationType, SwimlaneSecretConfigurationType, ExecutorParams, SwimlaneExecutorResultData | {} > { - const { logger } = params; - return { id: '.swimlane', minimumLicenseRequired: 'gold', @@ -75,19 +65,18 @@ export function getConnectorType( schema: ExecutorParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, }; } async function executor( - { logger }: { logger: Logger }, execOptions: ConnectorTypeExecutorOptions< SwimlanePublicConfigurationType, SwimlaneSecretConfigurationType, ExecutorParams > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; const { subAction, subActionParams } = params as ExecutorParams; let data: SwimlaneExecutorResultData | null = null; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts index 55fd99c040941..ead127d7dd521 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts @@ -6,8 +6,6 @@ */ import { registerConnectorTypes } from '.'; -import { Logger } from '@kbn/core/server'; -import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; const ACTION_TYPE_IDS = [ @@ -22,7 +20,6 @@ const ACTION_TYPE_IDS = [ '.xmatters', ]; -const logger = loggingSystemMock.create().get() as jest.Mocked; const mockedActions = actionsMock.createSetup(); beforeEach(() => { @@ -32,7 +29,6 @@ beforeEach(() => { describe('registers connectors', () => { test('calls registerType with expected connector types', () => { registerConnectorTypes({ - logger, actions: mockedActions, }); ACTION_TYPE_IDS.forEach((id) => diff --git a/x-pack/plugins/stack_connectors/server/connector_types/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/index.ts index 5aa352986939e..dd12f93bbc607 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { Logger } from '@kbn/core/server'; import { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server'; import { getEmailConnectorType, @@ -65,27 +64,25 @@ export { export function registerConnectorTypes({ actions, - logger, publicBaseUrl, }: { actions: ActionsPluginSetupContract; - logger: Logger; publicBaseUrl?: string; }) { - actions.registerType(getEmailConnectorType({ logger, publicBaseUrl })); - actions.registerType(getIndexConnectorType({ logger })); - actions.registerType(getPagerDutyConnectorType({ logger })); - actions.registerType(getSwimlaneConnectorType({ logger })); - actions.registerType(getServerLogConnectorType({ logger })); - actions.registerType(getSlackConnectorType({ logger })); - actions.registerType(getWebhookConnectorType({ logger })); - actions.registerType(getCasesWebhookConnectorType({ logger })); - actions.registerType(getXmattersConnectorType({ logger })); - actions.registerType(getServiceNowITSMConnectorType({ logger })); - actions.registerType(getServiceNowSIRConnectorType({ logger })); - actions.registerType(getServiceNowITOMConnectorType({ logger })); - actions.registerType(getJiraConnectorType({ logger })); - actions.registerType(getResilientConnectorType({ logger })); - actions.registerType(getTeamsConnectorType({ logger })); + actions.registerType(getEmailConnectorType({ publicBaseUrl })); + actions.registerType(getIndexConnectorType()); + actions.registerType(getPagerDutyConnectorType()); + actions.registerType(getSwimlaneConnectorType()); + actions.registerType(getServerLogConnectorType()); + actions.registerType(getSlackConnectorType({})); + actions.registerType(getWebhookConnectorType()); + actions.registerType(getCasesWebhookConnectorType()); + actions.registerType(getXmattersConnectorType()); + actions.registerType(getServiceNowITSMConnectorType()); + actions.registerType(getServiceNowSIRConnectorType()); + actions.registerType(getServiceNowITOMConnectorType()); + actions.registerType(getJiraConnectorType()); + actions.registerType(getResilientConnectorType()); + actions.registerType(getTeamsConnectorType()); actions.registerSubActionConnectorType(getOpsgenieConnectorType()); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.test.ts index ab5f909ecd4f7..4ce412e037df2 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.test.ts @@ -42,9 +42,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { jest.resetAllMocks(); configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType({}); }); describe('connector registration', () => { @@ -522,6 +520,7 @@ describe('execute()', () => { secrets, services, configurationUtilities: actionsConfigMock.create(), + logger: mockedLogger, }; test('ensure parameters are as expected', async () => { @@ -741,7 +740,6 @@ describe('execute()', () => { test('provides a footer link to Kibana when publicBaseUrl is defined', async () => { const connectorTypeWithPublicUrl = getConnectorType({ - logger: mockedLogger, publicBaseUrl: 'https://localhost:1234/foo/bar', }); @@ -760,7 +758,6 @@ describe('execute()', () => { test('allows to generate a deep link into Kibana when publicBaseUrl is defined', async () => { const connectorTypeWithPublicUrl = getConnectorType({ - logger: mockedLogger, publicBaseUrl: 'https://localhost:1234/foo/bar', }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.ts index e146baba68fbc..4fdbc1106bb9a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/email/index.ts @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import nodemailerGetService from 'nodemailer/lib/well-known'; import SMTPConnection from 'nodemailer/lib/smtp-connection'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -192,7 +191,6 @@ function validateParams(paramsObject: unknown, validatorServices: ValidatorServi } interface GetConnectorTypeParams { - logger: Logger; publicBaseUrl?: string; } @@ -218,7 +216,7 @@ function validateConnector( // connector type definition export const ConnectorTypeId = '.email'; export function getConnectorType(params: GetConnectorTypeParams): EmailConnectorType { - const { logger, publicBaseUrl } = params; + const { publicBaseUrl } = params; return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -245,7 +243,7 @@ export function getConnectorType(params: GetConnectorTypeParams): EmailConnector connector: validateConnector, }, renderParameterTemplates, - executor: curry(executor)({ logger, publicBaseUrl }), + executor: curry(executor)({ publicBaseUrl }), }; } @@ -265,20 +263,15 @@ function renderParameterTemplates( async function executor( { - logger, publicBaseUrl, }: { - logger: GetConnectorTypeParams['logger']; publicBaseUrl: GetConnectorTypeParams['publicBaseUrl']; }, execOptions: EmailConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const config = execOptions.config; - const secrets = execOptions.secrets; - const params = execOptions.params; - const configurationUtilities = execOptions.configurationUtilities; - const connectorTokenClient = execOptions.services.connectorTokenClient; + const { actionId, config, secrets, params, configurationUtilities, services, logger } = + execOptions; + const connectorTokenClient = services.connectorTokenClient; const emails = params.to.concat(params.cc).concat(params.bcc); let invalidEmailsMessage = configurationUtilities.validateEmailAddresses(emails); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.test.ts index 9968a67e87b45..d2961d4725d39 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.test.ts @@ -31,9 +31,7 @@ let configurationUtilities: ActionsConfigurationUtilities; beforeEach(() => { jest.resetAllMocks(); configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('connector registration', () => { @@ -186,6 +184,7 @@ describe('execute()', () => { params, services, configurationUtilities, + logger: mockedLogger, }; const scopedClusterClient = elasticsearchClientMock .createClusterClient() @@ -223,7 +222,15 @@ describe('execute()', () => { indexOverride: null, }; - executorOptions = { actionId, config, secrets, params, services, configurationUtilities }; + executorOptions = { + actionId, + config, + secrets, + params, + services, + configurationUtilities, + logger: mockedLogger, + }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ ...executorOptions, @@ -265,7 +272,15 @@ describe('execute()', () => { indexOverride: null, }; - executorOptions = { actionId, config, secrets, params, services, configurationUtilities }; + executorOptions = { + actionId, + config, + secrets, + params, + services, + configurationUtilities, + logger: mockedLogger, + }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ @@ -301,7 +316,15 @@ describe('execute()', () => { indexOverride: null, }; - executorOptions = { actionId, config, secrets, params, services, configurationUtilities }; + executorOptions = { + actionId, + config, + secrets, + params, + services, + configurationUtilities, + logger: mockedLogger, + }; scopedClusterClient.bulk.mockClear(); await connectorType.executor({ ...executorOptions, @@ -612,6 +635,7 @@ describe('execute()', () => { params, services, configurationUtilities, + logger: mockedLogger, }) ).toMatchInlineSnapshot(` Object { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.ts index d66f60233f49f..4f39111a4bb3d 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/es_index/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { curry, find } from 'lodash'; +import { find } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { Logger } from '@kbn/core/server'; @@ -70,7 +70,7 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.index'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): ESIndexConnectorType { +export function getConnectorType(): ESIndexConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'basic', @@ -90,7 +90,7 @@ export function getConnectorType({ logger }: { logger: Logger }): ESIndexConnect schema: ParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, renderParameterTemplates, }; } @@ -98,14 +98,9 @@ export function getConnectorType({ logger }: { logger: Logger }): ESIndexConnect // action executor async function executor( - { logger }: { logger: Logger }, execOptions: ESIndexConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const config = execOptions.config; - const params = execOptions.params; - const services = execOptions.services; - + const { actionId, config, params, services, logger } = execOptions; const index = params.indexOverride || config.index; const bulkBody = []; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.test.ts index eaf073f732f77..10752e53ae72a 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.test.ts @@ -34,9 +34,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('get()', () => { @@ -75,9 +73,7 @@ describe('validateConfig()', () => { expect(url).toEqual('https://events.pagerduty.com/v2/enqueue'); }, }; - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); expect( validateConfig( @@ -95,9 +91,7 @@ describe('validateConfig()', () => { throw new Error(`target url is not added to allowedHosts`); }, }; - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); expect(() => { validateConfig( @@ -274,6 +268,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -335,6 +330,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -401,6 +397,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -458,6 +455,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -500,6 +498,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -529,6 +528,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -558,6 +558,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -587,6 +588,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); expect(actionResponse).toMatchInlineSnapshot(` @@ -626,6 +628,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -688,6 +691,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -753,6 +757,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; @@ -817,6 +822,7 @@ describe('execute()', () => { secrets, services, configurationUtilities, + logger: mockedLogger, }; const actionResponse = await connectorType.executor(executorOptions); const { apiUrl, data, headers } = postPagerdutyMock.mock.calls[0][0]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.ts index e09f6159d26d8..e2b7a6998bda3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/pagerduty/index.ts @@ -5,11 +5,10 @@ * 2.0. */ -import { curry, isUndefined, pick, omitBy } from 'lodash'; +import { isUndefined, pick, omitBy } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import moment from 'moment'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -138,7 +137,7 @@ function validateParams(paramsObject: unknown): string | void { export const ConnectorTypeId = '.pagerduty'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): PagerDutyConnectorType { +export function getConnectorType(): PagerDutyConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -162,7 +161,7 @@ export function getConnectorType({ logger }: { logger: Logger }): PagerDutyConne schema: ParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, }; } @@ -192,15 +191,10 @@ function getPagerDutyApiUrl(config: ConnectorTypeConfigType): string { // action executor async function executor( - { logger }: { logger: Logger }, execOptions: PagerDutyConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const config = execOptions.config; - const secrets = execOptions.secrets; - const params = execOptions.params; - const services = execOptions.services; - const configurationUtilities = execOptions.configurationUtilities; + const { actionId, config, secrets, params, services, configurationUtilities, logger } = + execOptions; const apiUrl = getPagerDutyApiUrl(config); const headers = { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.test.ts index 04c8f9e562f79..082098023fc3f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.test.ts @@ -20,9 +20,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('connectorType', () => { @@ -108,6 +106,7 @@ describe('execute()', () => { config: {}, secrets: {}, configurationUtilities, + logger: mockedLogger, }; await connectorType.executor(executorOptions); expect(mockedLogger.info).toHaveBeenCalledWith('Server log: message text here'); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.ts index 23bfe27466349..f3e1e8e8af856 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/server_log/index.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { curry } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; @@ -49,7 +48,7 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.server-log'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): ServerLogConnectorType { +export function getConnectorType(): ServerLogConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'basic', @@ -62,18 +61,16 @@ export function getConnectorType({ logger }: { logger: Logger }): ServerLogConne schema: ParamsSchema, }, }, - executor: curry(executor)({ logger }), + executor, }; } // action executor async function executor( - { logger }: { logger: Logger }, execOptions: ServerLogConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const params = execOptions.params; + const { actionId, params, logger } = execOptions; const sanitizedMessage = withoutControlCharacters(params.message); try { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/servicenow_itom/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/servicenow_itom/index.ts index c6d1c5d772899..b04b2fcbc60a8 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/servicenow_itom/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/servicenow_itom/index.ts @@ -7,7 +7,6 @@ import { curry } from 'lodash'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -47,10 +46,6 @@ import { createServiceWrapper } from '../../lib/servicenow/create_service_wrappe export { ServiceNowITOMConnectorTypeId }; -interface GetConnectorTypeParams { - logger: Logger; -} - export type ServiceNowConnectorType< C extends Record = ServiceNowPublicConfigurationBaseType, T extends Record = ExecutorParamsITOM @@ -62,10 +57,10 @@ export type ServiceNowConnectorTypeExecutorOptions< > = ConnectorTypeExecutorOptions; // connector type definition -export function getServiceNowITOMConnectorType( - params: GetConnectorTypeParams -): ServiceNowConnectorType { - const { logger } = params; +export function getServiceNowITOMConnectorType(): ServiceNowConnectorType< + ServiceNowPublicConfigurationBaseType, + ExecutorParamsITOM +> { return { id: ServiceNowITOMConnectorTypeId, minimumLicenseRequired: 'platinum', @@ -86,7 +81,6 @@ export function getServiceNowITOMConnectorType( }, }, executor: curry(executorITOM)({ - logger, actionTypeId: ServiceNowITOMConnectorTypeId, createService: createExternalService, api: apiITOM, @@ -98,12 +92,10 @@ export function getServiceNowITOMConnectorType( const supportedSubActionsITOM = ['addEvent', 'getChoices']; async function executorITOM( { - logger, actionTypeId, createService, api, }: { - logger: Logger; actionTypeId: string; createService: ServiceFactory; api: ExternalServiceApiITOM; @@ -113,7 +105,7 @@ async function executorITOM( ExecutorParamsITOM > ): Promise> { - const { actionId, config, params, secrets, configurationUtilities } = execOptions; + const { actionId, config, params, secrets, configurationUtilities, logger } = execOptions; const { subAction, subActionParams } = params; const connectorTokenClient = execOptions.services.connectorTokenClient; const externalServiceConfig = snExternalServiceConfig[actionTypeId]; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.test.ts index 742cfd7ed1f60..f96cc176e467e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.test.ts @@ -42,7 +42,6 @@ beforeEach(() => { async executor(options) { return { status: 'ok', actionId: options.actionId }; }, - logger: mockedLogger, }); }); @@ -170,7 +169,6 @@ describe('execute()', () => { connectorType = getConnectorType({ executor: mockSlackExecutor, - logger: mockedLogger, }); }); @@ -182,6 +180,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities, + logger: mockedLogger, }); expect(response).toMatchInlineSnapshot(` Object { @@ -201,6 +200,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'failure: this invocation should fail' }, configurationUtilities, + logger: mockedLogger, }) ).rejects.toThrowErrorMatchingInlineSnapshot( `"slack mockExecutor failure: this invocation should fail"` @@ -217,9 +217,7 @@ describe('execute()', () => { proxyBypassHosts: undefined, proxyOnlyHosts: undefined, }); - const connectorTypeProxy = getConnectorType({ - logger: mockedLogger, - }); + const connectorTypeProxy = getConnectorType({}); await connectorTypeProxy.executor({ actionId: 'some-id', services, @@ -227,6 +225,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, + logger: mockedLogger, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -244,9 +243,7 @@ describe('execute()', () => { proxyBypassHosts: new Set(['example.com']), proxyOnlyHosts: undefined, }); - const connectorTypeProxy = getConnectorType({ - logger: mockedLogger, - }); + const connectorTypeProxy = getConnectorType({}); await connectorTypeProxy.executor({ actionId: 'some-id', services, @@ -254,6 +251,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, + logger: mockedLogger, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -271,9 +269,7 @@ describe('execute()', () => { proxyBypassHosts: new Set(['not-example.com']), proxyOnlyHosts: undefined, }); - const connectorTypeProxy = getConnectorType({ - logger: mockedLogger, - }); + const connectorTypeProxy = getConnectorType({}); await connectorTypeProxy.executor({ actionId: 'some-id', services, @@ -281,6 +277,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, + logger: mockedLogger, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -298,9 +295,7 @@ describe('execute()', () => { proxyBypassHosts: undefined, proxyOnlyHosts: new Set(['example.com']), }); - const connectorTypeProxy = getConnectorType({ - logger: mockedLogger, - }); + const connectorTypeProxy = getConnectorType({}); await connectorTypeProxy.executor({ actionId: 'some-id', services, @@ -308,6 +303,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, + logger: mockedLogger, }); expect(mockedLogger.debug).toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' @@ -325,9 +321,7 @@ describe('execute()', () => { proxyBypassHosts: undefined, proxyOnlyHosts: new Set(['not-example.com']), }); - const connectorTypeProxy = getConnectorType({ - logger: mockedLogger, - }); + const connectorTypeProxy = getConnectorType({}); await connectorTypeProxy.executor({ actionId: 'some-id', services, @@ -335,6 +329,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities: configUtils, + logger: mockedLogger, }); expect(mockedLogger.debug).not.toHaveBeenCalledWith( 'IncomingWebhook was called with proxyUrl https://someproxyhost' diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.ts index 343d353443f51..11b8cc0ad7196 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/slack/index.ts @@ -6,7 +6,6 @@ */ import { URL } from 'url'; -import { curry } from 'lodash'; import HttpProxyAgent from 'http-proxy-agent'; import { HttpsProxyAgent } from 'https-proxy-agent'; import { i18n } from '@kbn/i18n'; @@ -14,7 +13,6 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { IncomingWebhook, IncomingWebhookResult } from '@slack/webhook'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -65,10 +63,8 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.slack'; // customizing executor is only used for tests export function getConnectorType({ - logger, - executor = curry(slackExecutor)({ logger }), + executor = slackExecutor, }: { - logger: Logger; executor?: ExecutorType<{}, ConnectorTypeSecretsType, ActionParamsType, unknown>; }): SlackConnectorType { return { @@ -138,13 +134,9 @@ function validateConnectorTypeConfig( // action executor async function slackExecutor( - { logger }: { logger: Logger }, execOptions: SlackConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const secrets = execOptions.secrets; - const params = execOptions.params; - const configurationUtilities = execOptions.configurationUtilities; + const { actionId, secrets, params, configurationUtilities, logger } = execOptions; let result: IncomingWebhookResult; const { webhookUrl } = secrets; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.test.ts index a45db6021bfd7..6d1cbb2bfbbbe 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.test.ts @@ -37,9 +37,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('connector registration', () => { @@ -168,6 +166,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities, + logger: mockedLogger, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` @@ -222,6 +221,7 @@ describe('execute()', () => { secrets: { webhookUrl: 'http://example.com' }, params: { message: 'this invocation should succeed' }, configurationUtilities, + logger: mockedLogger, }); delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.ts index 3405f59a68f7a..df44d568a2f30 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/teams/index.ts @@ -6,13 +6,12 @@ */ import { URL } from 'url'; -import { curry, isString } from 'lodash'; +import { isString } from 'lodash'; import axios, { AxiosError, AxiosResponse } from 'axios'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -59,7 +58,7 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.teams'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): TeamsConnectorType { +export function getConnectorType(): TeamsConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -80,7 +79,7 @@ export function getConnectorType({ logger }: { logger: Logger }): TeamsConnector schema: ParamsSchema, }, }, - executor: curry(teamsExecutor)({ logger }), + executor: teamsExecutor, }; } @@ -117,13 +116,9 @@ function validateConnectorTypeConfig( // action executor async function teamsExecutor( - { logger }: { logger: Logger }, execOptions: TeamsConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const secrets = execOptions.secrets; - const params = execOptions.params; - const configurationUtilities = execOptions.configurationUtilities; + const { actionId, secrets, params, configurationUtilities, logger } = execOptions; const { webhookUrl } = secrets; const { message } = params; const data = { text: message }; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.test.ts index 5d82212e67179..4e3369af35c56 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.test.ts @@ -46,9 +46,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('connectorType', () => { @@ -271,6 +269,7 @@ describe('execute()', () => { secrets: { user: 'abc', password: '123' }, params: { body: 'some data' }, configurationUtilities, + logger: mockedLogger, }); delete requestMock.mock.calls[0][0].configurationUtilities; @@ -336,6 +335,7 @@ describe('execute()', () => { secrets: { user: 'abc', password: '123' }, params: { body: 'some data' }, configurationUtilities, + logger: mockedLogger, }); expect(mockedLogger.error).toBeCalledWith( 'error on some-id webhook event: maxContentLength size of 1000000 exceeded' @@ -359,6 +359,7 @@ describe('execute()', () => { secrets, params: { body: 'some data' }, configurationUtilities, + logger: mockedLogger, }); delete requestMock.mock.calls[0][0].configurationUtilities; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.ts index bc25d65d45915..0656cb0692e37 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/webhook/index.ts @@ -6,12 +6,11 @@ */ import { i18n } from '@kbn/i18n'; -import { curry, isString } from 'lodash'; +import { isString } from 'lodash'; import axios, { AxiosError, AxiosResponse } from 'axios'; import { schema, TypeOf } from '@kbn/config-schema'; import { pipe } from 'fp-ts/lib/pipeable'; import { map, getOrElse } from 'fp-ts/lib/Option'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -84,7 +83,7 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.webhook'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): WebhookConnectorType { +export function getConnectorType(): WebhookConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -109,7 +108,7 @@ export function getConnectorType({ logger }: { logger: Logger }): WebhookConnect }, }, renderParameterTemplates, - executor: curry(executor)({ logger }), + executor, }; } @@ -158,13 +157,11 @@ function validateConnectorTypeConfig( // action executor export async function executor( - { logger }: { logger: Logger }, execOptions: WebhookConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const { method, url, headers = {}, hasAuth } = execOptions.config; - const { body: data } = execOptions.params; - const configurationUtilities = execOptions.configurationUtilities; + const { actionId, config, params, configurationUtilities, logger } = execOptions; + const { method, url, headers = {}, hasAuth } = config; + const { body: data } = params; const secrets: ConnectorTypeSecretsType = execOptions.secrets; const basicAuth = diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.test.ts index 98cac875e6b55..f39f510282984 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.test.ts @@ -38,9 +38,7 @@ let configurationUtilities: jest.Mocked; beforeEach(() => { configurationUtilities = actionsConfigMock.create(); - connectorType = getConnectorType({ - logger: mockedLogger, - }); + connectorType = getConnectorType(); }); describe('connectorType', () => { @@ -414,6 +412,7 @@ describe('execute()', () => { tags: 'test1, test2', }, configurationUtilities, + logger: mockedLogger, }); expect(postxMattersMock.mock.calls[0][0]).toMatchInlineSnapshot(` @@ -462,6 +461,7 @@ describe('execute()', () => { tags: 'test1, test2', }, configurationUtilities, + logger: mockedLogger, }); expect(mockedLogger.warn).toBeCalledWith( 'Error thrown triggering xMatters workflow: maxContentLength size of 1000000 exceeded' @@ -493,6 +493,7 @@ describe('execute()', () => { tags: 'test1, test2', }, configurationUtilities, + logger: mockedLogger, }); expect(postxMattersMock.mock.calls[0][0]).toMatchInlineSnapshot(` diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.ts index 0686d37a953f5..b34e300a496ed 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/xmatters/index.ts @@ -5,10 +5,9 @@ * 2.0. */ -import { curry, isString } from 'lodash'; +import { isString } from 'lodash'; import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; -import { Logger } from '@kbn/core/server'; import type { ActionType as ConnectorType, ActionTypeExecutorOptions as ConnectorTypeExecutorOptions, @@ -60,7 +59,7 @@ const ParamsSchema = schema.object({ export const ConnectorTypeId = '.xmatters'; // connector type definition -export function getConnectorType({ logger }: { logger: Logger }): XmattersConnectorType { +export function getConnectorType(): XmattersConnectorType { return { id: ConnectorTypeId, minimumLicenseRequired: 'gold', @@ -82,7 +81,7 @@ export function getConnectorType({ logger }: { logger: Logger }): XmattersConnec }, connector: validateConnector, }, - executor: curry(executor)({ logger }), + executor, }; } @@ -243,13 +242,11 @@ function validateConnectorTypeSecrets( // action executor export async function executor( - { logger }: { logger: Logger }, execOptions: XmattersConnectorTypeExecutorOptions ): Promise> { - const actionId = execOptions.actionId; - const configurationUtilities = execOptions.configurationUtilities; - const { configUrl, usesBasic } = execOptions.config; - const data = getPayloadForRequest(execOptions.params); + const { actionId, configurationUtilities, config, params, logger } = execOptions; + const { configUrl, usesBasic } = config; + const data = getPayloadForRequest(params); const secrets: ConnectorTypeSecretsType = execOptions.secrets; const basicAuth = diff --git a/x-pack/plugins/stack_connectors/server/plugin.ts b/x-pack/plugins/stack_connectors/server/plugin.ts index 0c8b32b49d9f4..ce1795b4eb7fb 100644 --- a/x-pack/plugins/stack_connectors/server/plugin.ts +++ b/x-pack/plugins/stack_connectors/server/plugin.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { PluginInitializerContext, Plugin, CoreSetup, Logger } from '@kbn/core/server'; +import { PluginInitializerContext, Plugin, CoreSetup } from '@kbn/core/server'; import { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server'; import { registerConnectorTypes } from './connector_types'; import { getWellKnownEmailServiceRoute } from './routes'; @@ -18,11 +18,7 @@ export interface ConnectorsPluginsStart { } export class StackConnectorsPlugin implements Plugin { - private readonly logger: Logger; - - constructor(context: PluginInitializerContext) { - this.logger = context.logger.get(); - } + constructor(context: PluginInitializerContext) {} public setup(core: CoreSetup, plugins: ConnectorsPluginsSetup) { const router = core.http.createRouter(); @@ -31,7 +27,6 @@ export class StackConnectorsPlugin implements Plugin { getWellKnownEmailServiceRoute(router); registerConnectorTypes({ - logger: this.logger, actions, publicBaseUrl: core.http.basePath.publicBaseUrl, }); diff --git a/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts b/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts index ff2aefa12d94d..9f40d49d7086b 100644 --- a/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts +++ b/x-pack/plugins/synthetics/common/constants/monitor_defaults.ts @@ -47,6 +47,7 @@ export const DEFAULT_COMMON_FIELDS: CommonFields = { [ConfigKey.NAMESPACE]: DEFAULT_NAMESPACE_STRING, [ConfigKey.MONITOR_SOURCE_TYPE]: SourceType.UI, [ConfigKey.JOURNEY_ID]: '', + [ConfigKey.CONFIG_HASH]: '', // Deprecated, slated to be removed in a future version [ConfigKey.ID]: '', diff --git a/x-pack/plugins/synthetics/common/constants/monitor_management.ts b/x-pack/plugins/synthetics/common/constants/monitor_management.ts index da3f138091723..bdf5dc6548f20 100644 --- a/x-pack/plugins/synthetics/common/constants/monitor_management.ts +++ b/x-pack/plugins/synthetics/common/constants/monitor_management.ts @@ -10,6 +10,7 @@ export enum ConfigKey { APM_SERVICE_NAME = 'service.name', CUSTOM_HEARTBEAT_ID = 'custom_heartbeat_id', CONFIG_ID = 'config_id', + CONFIG_HASH = 'hash', ENABLED = 'enabled', FORM_MONITOR_TYPE = 'form_monitor_type', HOSTS = 'hosts', diff --git a/x-pack/plugins/synthetics/common/constants/rest_api.ts b/x-pack/plugins/synthetics/common/constants/rest_api.ts index dad434194f21d..0f43ff654c77e 100644 --- a/x-pack/plugins/synthetics/common/constants/rest_api.ts +++ b/x-pack/plugins/synthetics/common/constants/rest_api.ts @@ -48,5 +48,6 @@ export enum API_URLS { SYNTHETICS_HAS_ZIP_URL_MONITORS = '/internal/uptime/fleet/has_zip_url_monitors', // Project monitor public endpoint - SYNTHETICS_MONITORS_PROJECT = '/api/synthetics/service/project/monitors', + SYNTHETICS_MONITORS_PROJECT_LEGACY = '/api/synthetics/service/project/monitors', + SYNTHETICS_MONITORS_PROJECT = '/api/synthetics/project/{projectName}/monitors', } diff --git a/x-pack/plugins/synthetics/common/formatters/common/formatters.ts b/x-pack/plugins/synthetics/common/formatters/common/formatters.ts index 882182b2fe07f..ab7c3bc9cfa29 100644 --- a/x-pack/plugins/synthetics/common/formatters/common/formatters.ts +++ b/x-pack/plugins/synthetics/common/formatters/common/formatters.ts @@ -32,6 +32,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.PROJECT_ID]: null, [ConfigKey.CUSTOM_HEARTBEAT_ID]: null, [ConfigKey.ORIGINAL_SPACE]: null, + [ConfigKey.CONFIG_HASH]: null, // Deprecated, slated to be removed in a later release [ConfigKey.ID]: null, diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts index 163041986f1a3..78bca7a681461 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types.ts @@ -82,6 +82,7 @@ export const CommonFieldsCodec = t.intersection([ [ConfigKey.REVISION]: t.number, [ConfigKey.MONITOR_SOURCE_TYPE]: SourceTypeCodec, [ConfigKey.CONFIG_ID]: t.string, + [ConfigKey.CONFIG_HASH]: t.string, [ConfigKey.JOURNEY_ID]: t.string, [ConfigKey.PROJECT_ID]: t.string, [ConfigKey.ORIGINAL_SPACE]: t.string, diff --git a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts index cba2f506189e6..ef5f6a23b4413 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts @@ -40,6 +40,7 @@ export const ProjectMonitorCodec = t.intersection([ hosts: t.union([t.string, t.array(t.string)]), max_redirects: t.string, wait: t.string, + hash: t.string, }), ]); @@ -49,8 +50,27 @@ export const ProjectMonitorsRequestCodec = t.interface({ monitors: t.array(ProjectMonitorCodec), }); +export const ProjectMonitorMetaDataCodec = t.interface({ + hash: t.string, + journey_id: t.string, +}); + +export const ProjectMonitorsResponseCodec = t.intersection([ + t.interface({ + total: t.number, + monitors: t.array(ProjectMonitorMetaDataCodec), + }), + t.partial({ + after_key: t.string, + }), +]); + export type ProjectMonitorThrottlingConfig = t.TypeOf; export type ProjectMonitor = t.TypeOf; export type ProjectMonitorsRequest = t.TypeOf; + +export type ProjectMonitorsResponse = t.TypeOf; + +export type ProjectMonitorMetaData = t.TypeOf; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx index 2903a0375d038..d13213766c3db 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx @@ -6,6 +6,8 @@ */ import { format } from './formatter'; +import { DataStream } from '../../../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../../../common/constants/monitor_defaults'; describe('format', () => { let formValues: Record; @@ -88,6 +90,7 @@ describe('format', () => { it.each([[true], [false]])('correctly formats form fields to monitor type', (enabled) => { formValues.enabled = enabled; expect(format(formValues)).toEqual({ + ...DEFAULT_FIELDS[DataStream.HTTP], __ui: { is_tls_enabled: false, }, @@ -223,6 +226,7 @@ describe('format', () => { }, }; expect(format(browserFormFields)).toEqual({ + ...DEFAULT_FIELDS[DataStream.BROWSER], __ui: { script_source: { file_name: fileName, @@ -304,6 +308,7 @@ describe('format', () => { }, }) ).toEqual({ + ...DEFAULT_FIELDS[DataStream.HTTP], __ui: { is_tls_enabled: isTLSEnabled, }, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx index 2017109855bfb..6b9ab1442b9eb 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx @@ -7,6 +7,7 @@ import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { ConfigKey } from '../../../../../../common/runtime_types'; import { getMonitorRecentPingsAction, selectLatestPing, selectPingsLoading } from '../../../state'; import { useSelectedLocation } from './use_selected_location'; import { useSelectedMonitor } from './use_selected_monitor'; @@ -28,10 +29,14 @@ export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => { const latestPing = useSelector(selectLatestPing); const pingsLoading = useSelector(selectPingsLoading); - const isUpToDate = - latestPing && - latestPing.monitor.id === monitorId && - latestPing.observer?.geo?.name === locationLabel; + const latestPingId = latestPing?.monitor.id; + + const isIdSame = + latestPingId === monitorId || latestPingId === monitor?.[ConfigKey.CUSTOM_HEARTBEAT_ID]; + + const isLocationSame = latestPing?.observer?.geo?.name === locationLabel; + + const isUpToDate = isIdSame && isLocationSame; useEffect(() => { if (monitorId && locationLabel && !isUpToDate) { @@ -47,7 +52,7 @@ export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => { return { loading: pingsLoading, latestPing: null }; } - if (latestPing.monitor.id !== monitorId || latestPing.observer?.geo?.name !== locationLabel) { + if (!isIdSame || !isLocationSame) { return { loading: pingsLoading, latestPing: null }; } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_query_id.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_query_id.ts new file mode 100644 index 0000000000000..4b1e88461fa16 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_query_id.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useParams } from 'react-router-dom'; +import { ConfigKey } from '../../../../../../common/runtime_types'; +import { useSelectedMonitor } from './use_selected_monitor'; + +export const useMonitorQueryId = () => { + const { monitorId } = useParams<{ monitorId: string }>(); + + const { monitor } = useSelectedMonitor(); + + if (monitor && monitor.origin === 'project') { + return monitor[ConfigKey.CUSTOM_HEARTBEAT_ID]!; + } + + return monitorId; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/availability_sparklines.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/availability_sparklines.tsx index bc05d8fcc7a51..308ba581f6b0b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/availability_sparklines.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/availability_sparklines.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ReportTypes, useTheme } from '@kbn/observability-plugin/public'; -import { useParams } from 'react-router-dom'; import { ClientPluginsStart } from '../../../../../plugin'; +import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; export const AvailabilitySparklines = () => { const { @@ -17,7 +17,7 @@ export const AvailabilitySparklines = () => { observability: { ExploratoryViewEmbeddable }, }, } = useKibana(); - const { monitorId } = useParams<{ monitorId: string }>(); + const monitorId = useMonitorQueryId(); const theme = useTheme(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_panel.tsx index 6d3ff68b2785c..4c6ede0ade308 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_panel.tsx @@ -8,10 +8,10 @@ import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ReportTypes } from '@kbn/observability-plugin/public'; -import { useParams } from 'react-router-dom'; import { ClientPluginsStart } from '../../../../../plugin'; import { KpiWrapper } from './kpi_wrapper'; +import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; export const DurationPanel = () => { const { @@ -19,7 +19,7 @@ export const DurationPanel = () => { observability: { ExploratoryViewEmbeddable }, }, } = useKibana(); - const { monitorId } = useParams<{ monitorId: string }>(); + const monitorId = useMonitorQueryId(); return ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_trend.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_trend.tsx index 8336e33a7e973..3642aa520c211 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_trend.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_trend.tsx @@ -7,15 +7,15 @@ import React from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { useParams } from 'react-router-dom'; import { ClientPluginsStart } from '../../../../../plugin'; +import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; export const MonitorDurationTrend = () => { const { observability } = useKibana().services; const { ExploratoryViewEmbeddable } = observability; - const { monitorId } = useParams<{ monitorId: string }>(); + const monitorId = useMonitorQueryId(); const metricsToShow = ['min', 'max', 'median', '25th', '75th']; @@ -31,9 +31,7 @@ export const MonitorDurationTrend = () => { }, name: metric + ' Series', selectedMetricField: 'monitor.duration.us', - reportDefinitions: { - 'monitor.id': [monitorId], - }, + reportDefinitions: { 'monitor.id': [monitorId] }, seriesType: 'line', operationType: metric, }))} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx index 120449b88bd04..1fe6ef23a44a0 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/step_duration_panel.tsx @@ -9,9 +9,9 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText, EuiTitle } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { ReportTypes } from '@kbn/observability-plugin/public'; -import { useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; +import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; import { useSelectedMonitor } from '../hooks/use_selected_monitor'; import { ClientPluginsStart } from '../../../../../plugin'; export const StepDurationPanel = () => { @@ -19,10 +19,10 @@ export const StepDurationPanel = () => { const { ExploratoryViewEmbeddable } = observability; - const { monitorId } = useParams<{ monitorId: string }>(); - const { monitor } = useSelectedMonitor(); + const monitorId = useMonitorQueryId(); + const isBrowser = monitor?.type === 'browser'; return ( diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts index 31ba9784e22a4..f4678b5569872 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/common/normalizers.ts @@ -96,6 +96,7 @@ export const commonNormalizers: CommonNormalizerMap = { [ConfigKey.PROJECT_ID]: getCommonNormalizer(ConfigKey.PROJECT_ID), [ConfigKey.CUSTOM_HEARTBEAT_ID]: getCommonNormalizer(ConfigKey.CUSTOM_HEARTBEAT_ID), [ConfigKey.ORIGINAL_SPACE]: getCommonNormalizer(ConfigKey.ORIGINAL_SPACE), + [ConfigKey.CONFIG_HASH]: getCommonNormalizer(ConfigKey.CONFIG_HASH), // Deprecated, slated to be removed in a future release [ConfigKey.ID]: getCommonNormalizer(ConfigKey.ID), diff --git a/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/synthetics_monitor.ts b/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/synthetics_monitor.ts index 52be898373ef2..94a8a0085e170 100644 --- a/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/synthetics_monitor.ts +++ b/x-pack/plugins/synthetics/server/legacy_uptime/lib/saved_objects/synthetics_monitor.ts @@ -54,6 +54,9 @@ export const syntheticsMonitor: SavedObjectsType = { origin: { type: 'keyword', }, + hash: { + type: 'keyword', + }, locations: { properties: { id: { diff --git a/x-pack/plugins/synthetics/server/routes/common.ts b/x-pack/plugins/synthetics/server/routes/common.ts index bdf06c8373af3..84a1a294f27e6 100644 --- a/x-pack/plugins/synthetics/server/routes/common.ts +++ b/x-pack/plugins/synthetics/server/routes/common.ts @@ -23,6 +23,8 @@ const querySchema = schema.object({ monitorType: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), locations: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), status: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + fields: schema.maybe(schema.arrayOf(schema.string())), + searchAfter: schema.maybe(schema.arrayOf(schema.string())), }); type MonitorsQuery = TypeOf; @@ -42,6 +44,8 @@ export const getMonitors = ( monitorType, locations, filter = '', + fields, + searchAfter, } = request as MonitorsQuery; const locationFilter = parseLocationFilter(syntheticsService.locations, locations); @@ -60,6 +64,8 @@ export const getMonitors = ( searchFields: ['name', 'tags.text', 'locations.id.text', 'urls'], search: query ? `${query}*` : undefined, filter: filters + filter, + fields, + searchAfter, }); }; diff --git a/x-pack/plugins/synthetics/server/routes/index.ts b/x-pack/plugins/synthetics/server/routes/index.ts index 63a2a0b889fe5..8cff5dc88c918 100644 --- a/x-pack/plugins/synthetics/server/routes/index.ts +++ b/x-pack/plugins/synthetics/server/routes/index.ts @@ -18,6 +18,7 @@ import { getSyntheticsMonitorOverviewRoute, getSyntheticsMonitorRoute, } from './monitor_cruds/get_monitor'; +import { getSyntheticsProjectMonitorsRoute } from './monitor_cruds/get_monitor_project'; import { runOnceSyntheticsMonitorRoute } from './synthetics_service/run_once_monitor'; import { getServiceAllowedRoute } from './synthetics_service/get_service_allowed'; import { testNowMonitorRoute } from './synthetics_service/test_now_monitor'; @@ -42,6 +43,7 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ enableSyntheticsRoute, getServiceLocationsRoute, getSyntheticsMonitorRoute, + getSyntheticsProjectMonitorsRoute, getAllSyntheticsMonitorRoute, getSyntheticsMonitorOverviewRoute, installIndexTemplatesRoute, diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts index ea269d87413e7..533690de30bed 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/add_monitor_project.ts @@ -19,7 +19,7 @@ export const addSyntheticsProjectMonitorRoute: SyntheticsStreamingRouteFactory = libs: UMServerLibs ) => ({ method: 'PUT', - path: API_URLS.SYNTHETICS_MONITORS_PROJECT, + path: API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY, validate: { body: schema.object({ project: schema.string(), diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts new file mode 100644 index 0000000000000..fc965b94cb096 --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/get_monitor_project.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { schema } from '@kbn/config-schema'; +import { ConfigKey } from '../../../common/runtime_types'; +import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types'; +import { API_URLS } from '../../../common/constants'; +import { syntheticsMonitorType } from '../../legacy_uptime/lib/saved_objects/synthetics_monitor'; +import { getMonitors } from '../common'; + +const querySchema = schema.object({ + search_after: schema.maybe(schema.string()), + per_page: schema.maybe(schema.number()), +}); + +export const getSyntheticsProjectMonitorsRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'GET', + path: API_URLS.SYNTHETICS_MONITORS_PROJECT, + validate: { + params: schema.object({ + projectName: schema.string(), + }), + query: querySchema, + }, + handler: async ({ + request, + response, + server: { logger }, + savedObjectsClient, + syntheticsMonitorClient, + }): Promise => { + const { projectName } = request.params; + const { per_page: perPage = 500, search_after: searchAfter } = request.query; + const decodedProjectName = decodeURI(projectName); + const decodedSearchAfter = searchAfter ? decodeURI(searchAfter) : undefined; + + try { + const { saved_objects: monitors, total } = await getMonitors( + { + filter: `${syntheticsMonitorType}.attributes.${ConfigKey.PROJECT_ID}: "${decodedProjectName}"`, + fields: [ConfigKey.JOURNEY_ID, ConfigKey.CONFIG_HASH], + perPage, + sortField: ConfigKey.JOURNEY_ID, + sortOrder: 'asc', + searchAfter: decodedSearchAfter ? [...decodedSearchAfter.split(',')] : undefined, + }, + syntheticsMonitorClient.syntheticsService, + savedObjectsClient + ); + const projectMonitors = monitors.map((monitor) => ({ + journey_id: monitor.attributes[ConfigKey.JOURNEY_ID], + hash: monitor.attributes[ConfigKey.CONFIG_HASH] || '', + })); + + return { + total, + after_key: monitors.length ? monitors[monitors.length - 1].sort?.join(',') : null, + monitors: projectMonitors, + }; + } catch (error) { + logger.error(error); + } + }, +}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts b/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts index 5e9f35f030bd8..f88f23ca38037 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/formatters/common.ts @@ -34,6 +34,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.PROJECT_ID]: null, [ConfigKey.CUSTOM_HEARTBEAT_ID]: null, [ConfigKey.ORIGINAL_SPACE]: null, + [ConfigKey.CONFIG_HASH]: null, // Deprecated, slated to be removed in a later releae [ConfigKey.ID]: null, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/formatters/format_configs.ts b/x-pack/plugins/synthetics/server/synthetics_service/formatters/format_configs.ts index a1c1d68c4a829..320d3c28b48d3 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/formatters/format_configs.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/formatters/format_configs.ts @@ -27,6 +27,7 @@ const UI_KEYS_TO_SKIP = [ ConfigKey.CUSTOM_HEARTBEAT_ID, ConfigKey.FORM_MONITOR_TYPE, ConfigKey.TEXT_ASSERTION, + ConfigKey.CONFIG_HASH, 'secrets', ]; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts index 3133e98b57935..a11a990abaa56 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/browser_monitor.test.ts @@ -18,6 +18,7 @@ import { normalizeProjectMonitors } from '.'; describe('browser normalizers', () => { describe('normalize push monitors', () => { + const testHash = 'ljlkj'; const playwrightOptions = { headless: true, }; @@ -67,6 +68,7 @@ describe('browser normalizers', () => { locations: ['us_central'], tags: ['tag1', 'tag2'], ignoreHTTPSErrors: true, + hash: testHash, } as ProjectMonitor, // test that normalizers defaults to browser when type is omitted { id: 'test-id-2', @@ -85,6 +87,7 @@ describe('browser normalizers', () => { tags: ['tag3', 'tag4'], ignoreHTTPSErrors: false, type: DataStream.BROWSER, + hash: testHash, }, { id: 'test-id-3', @@ -104,6 +107,7 @@ describe('browser normalizers', () => { tags: ['tag3', 'tag4'], ignoreHTTPSErrors: false, type: DataStream.BROWSER, + hash: testHash, }, ]; @@ -158,6 +162,7 @@ describe('browser normalizers', () => { custom_heartbeat_id: 'test-id-1-test-project-id-test-space', timeout: null, id: '', + hash: testHash, }, unsupportedKeys: [], errors: [], @@ -215,6 +220,7 @@ describe('browser normalizers', () => { custom_heartbeat_id: 'test-id-2-test-project-id-test-space', timeout: null, id: '', + hash: testHash, }, unsupportedKeys: [], errors: [], @@ -279,6 +285,7 @@ describe('browser normalizers', () => { custom_heartbeat_id: 'test-id-3-test-project-id-test-space', timeout: null, id: '', + hash: testHash, }, unsupportedKeys: [], errors: [], diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts index 56045712606a1..564de1c1c92d6 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts @@ -73,6 +73,7 @@ export const getNormalizeCommonFields = ({ [ConfigKey.TIMEOUT]: monitor.timeout ? getValueInSeconds(monitor.timeout) : defaultFields[ConfigKey.TIMEOUT], + [ConfigKey.CONFIG_HASH]: monitor.hash || defaultFields[ConfigKey.CONFIG_HASH], }; return normalizedFields; }; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts index 055c375bfb3b3..e80972f0a0c3b 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/http_monitor.test.ts @@ -5,10 +5,17 @@ * 2.0. */ -import { Locations, LocationStatus, PrivateLocation } from '../../../../common/runtime_types'; +import { + DataStream, + Locations, + LocationStatus, + PrivateLocation, +} from '../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; import { normalizeProjectMonitors } from '.'; describe('http normalizers', () => { + const testHash = 'ljlkj'; describe('normalize push monitors', () => { const projectId = 'test-project-id'; const locations: Locations = [ @@ -74,6 +81,7 @@ describe('http normalizers', () => { ssl: { supported_protocols: ['TLSv1.2', 'TLSv1.3'], }, + hash: testHash, }, { locations: ['localhost'], @@ -104,6 +112,7 @@ describe('http normalizers', () => { }, 'service.name': 'test service', 'ssl.supported_protocols': 'TLSv1.2,TLSv1.3', + hash: testHash, }, ]; @@ -133,6 +142,7 @@ describe('http normalizers', () => { }, ], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.HTTP], __ui: { is_tls_enabled: false, }, @@ -182,12 +192,14 @@ describe('http normalizers', () => { 'url.port': null, username: '', id: '', + hash: testHash, }, unsupportedKeys: ['check.response.body', 'unsupportedKey.nestedUnsupportedKey'], }, { errors: [], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.HTTP], __ui: { is_tls_enabled: false, }, @@ -237,6 +249,7 @@ describe('http normalizers', () => { 'url.port': null, username: '', id: '', + hash: testHash, }, unsupportedKeys: [], }, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.test.ts index 17bdd9e8ca24e..3c1d9209ff1bb 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/icmp_monitor.test.ts @@ -5,10 +5,17 @@ * 2.0. */ -import { Locations, LocationStatus, PrivateLocation } from '../../../../common/runtime_types'; +import { + DataStream, + Locations, + LocationStatus, + PrivateLocation, +} from '../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; import { normalizeProjectMonitors } from '.'; describe('icmp normalizers', () => { + const testHash = 'ljlkj'; describe('normalize push monitors', () => { const projectId = 'test-project-id'; const locations: Locations = [ @@ -51,6 +58,7 @@ describe('icmp normalizers', () => { timeout: '1m', wait: '30s', 'service.name': 'test service', + hash: testHash, }, { locations: ['us_central'], @@ -65,6 +73,7 @@ describe('icmp normalizers', () => { service: { name: 'test service', }, + hash: testHash, }, { locations: ['us_central'], @@ -78,6 +87,7 @@ describe('icmp normalizers', () => { unsupportedKey: { nestedUnsupportedKey: 'unnsuportedValue', }, + hash: testHash, }, ]; @@ -94,6 +104,7 @@ describe('icmp normalizers', () => { { errors: [], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.ICMP], config_id: '', custom_heartbeat_id: 'Cloudflare-DNS-test-project-id-test-space', enabled: true, @@ -128,12 +139,14 @@ describe('icmp normalizers', () => { type: 'icmp', wait: '30', id: '', + hash: testHash, }, unsupportedKeys: [], }, { errors: [], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.ICMP], config_id: '', custom_heartbeat_id: 'Cloudflare-DNS-2-test-project-id-test-space', enabled: true, @@ -168,6 +181,7 @@ describe('icmp normalizers', () => { type: 'icmp', wait: '60', id: '', + hash: testHash, }, unsupportedKeys: [], }, @@ -187,6 +201,7 @@ describe('icmp normalizers', () => { }, ], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.ICMP], config_id: '', custom_heartbeat_id: 'Cloudflare-DNS-3-test-project-id-test-space', enabled: true, @@ -221,6 +236,7 @@ describe('icmp normalizers', () => { type: 'icmp', wait: '1', id: '', + hash: testHash, }, unsupportedKeys: ['unsupportedKey.nestedUnsupportedKey'], }, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.test.ts index 9fbcb0c3b4ddf..79ea67964fd28 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/tcp_monitor.test.ts @@ -5,11 +5,18 @@ * 2.0. */ -import { Locations, LocationStatus, PrivateLocation } from '../../../../common/runtime_types'; +import { + DataStream, + Locations, + LocationStatus, + PrivateLocation, +} from '../../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../../common/constants/monitor_defaults'; import { normalizeProjectMonitors } from '.'; describe('tcp normalizers', () => { describe('normalize push monitors', () => { + const testHash = 'lleklrkelkj'; const projectId = 'test-project-id'; const locations: Locations = [ { @@ -50,6 +57,7 @@ describe('tcp normalizers', () => { privateLocations: ['BEEP'], 'service.name': 'test service', 'ssl.supported_protocols': ['TLSv1.2', 'TLSv1.3'], + hash: testHash, }, { locations: ['us_central'], @@ -66,6 +74,7 @@ describe('tcp normalizers', () => { ssl: { supported_protocols: 'TLSv1.2,TLSv1.3', }, + hash: testHash, }, { locations: ['us_central'], @@ -80,6 +89,7 @@ describe('tcp normalizers', () => { unsupportedKey: { nestedUnsupportedKey: 'unnsuportedValue', }, + hash: testHash, }, ]; @@ -96,6 +106,7 @@ describe('tcp normalizers', () => { { errors: [], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.TCP], __ui: { is_tls_enabled: false, }, @@ -144,12 +155,14 @@ describe('tcp normalizers', () => { type: 'tcp', id: '', urls: '', + hash: testHash, }, unsupportedKeys: [], }, { errors: [], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.TCP], __ui: { is_tls_enabled: false, }, @@ -198,6 +211,7 @@ describe('tcp normalizers', () => { type: 'tcp', id: '', urls: '', + hash: testHash, }, unsupportedKeys: [], }, @@ -217,6 +231,7 @@ describe('tcp normalizers', () => { }, ], normalizedFields: { + ...DEFAULT_FIELDS[DataStream.TCP], __ui: { is_tls_enabled: false, }, @@ -265,6 +280,7 @@ describe('tcp normalizers', () => { type: 'tcp', id: '', urls: '', + hash: testHash, }, unsupportedKeys: ['ports', 'unsupportedKey.nestedUnsupportedKey'], }, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts index 6cefad03b83fc..5892f53344d48 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/project_monitor_formatter.test.ts @@ -10,7 +10,8 @@ import { INSUFFICIENT_FLEET_PERMISSIONS, ProjectMonitorFormatter, } from './project_monitor_formatter'; -import { LocationStatus } from '../../../common/runtime_types'; +import { DataStream, LocationStatus } from '../../../common/runtime_types'; +import { DEFAULT_FIELDS } from '../../../common/constants/monitor_defaults'; import { times } from 'lodash'; import { SyntheticsService } from '../synthetics_service'; import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters'; @@ -45,6 +46,7 @@ const testMonitors = [ content: 'UEsDBBQACAAIAAAAIQAAAAAAAAAAAAAAAAAQAAAAYmFzaWMuam91cm5leS50c2WQQU7DQAxF9znFV8QiUUOmXcCCUMQl2NdMnWbKJDMaO6Ilyt0JASQkNv9Z1teTZWNAIqwP5kU4iZGOug863u7uDXsSddbIddCOl0kMX6iPnsVoOAYxryTO1ucwpoGvtUrm+hiSYsLProIoxwp8iWwVM9oUeuTP/9V5k7UhofCscNhj2yx4xN2CzabElOHXWRxsx/YNroU69QwniImFB8Vui5vJzYcKxYRIJ66WTNQL5hL7p1WD9aYi9zQOtgPFGPNqecJ1sCj+tAB6J6erpj4FDcW3qh6TL5u1Mq/8yjn7BFBLBwhGDIWc4QAAAEkBAABQSwECLQMUAAgACAAAACEARgyFnOEAAABJAQAAEAAAAAAAAAAAACAApIEAAAAAYmFzaWMuam91cm5leS50c1BLBQYAAAAAAQABAD4AAAAfAQAAAAA=', filter: { match: 'check if title is present 10 0' }, + hash: 'lleklrkelkj', }, { type: 'browser', @@ -68,6 +70,7 @@ const testMonitors = [ content: 'UEsDBBQACAAIAAAAIQAAAAAAAAAAAAAAAAAQAAAAYmFzaWMuam91cm5leS50c2WQQU7DQAxF9znFV8QiUUOmXcCCUMQl2NdMnWbKJDMaO6Ilyt0JASQkNv9Z1teTZWNAIqwP5kU4iZGOug863u7uDXsSddbIddCOl0kMX6iPnsVoOAYxryTO1ucwpoGvtUrm+hiSYsLProIoxwp8iWwVM9oUeuTP/9V5k7UhofCscNhj2yx4xN2CzabElOHXWRxsx/YNroU69QwniImFB8Vui5vJzYcKxYRIJ66WTNQL5hL7p1WD9aYi9zQOtgPFGPNqecJ1sCj+tAB6J6erpj4FDcW3qh6TL5u1Mq/8yjn7BFBLBwhGDIWc4QAAAEkBAABQSwECLQMUAAgACAAAACEARgyFnOEAAABJAQAAEAAAAAAAAAAAACAApIEAAAAAYmFzaWMuam91cm5leS50c1BLBQYAAAAAAQABAD4AAAAfAQAAAAA=', filter: { match: 'check if title is present 10 1' }, + hash: 'lleklrkelkj', }, ]; @@ -492,6 +495,7 @@ describe('ProjectMonitorFormatter', () => { const payloadData = [ { + ...DEFAULT_FIELDS[DataStream.BROWSER], __ui: { is_zip_url_tls_enabled: false, script_source: { @@ -550,8 +554,10 @@ const payloadData = [ 'url.port': null, urls: '', id: '', + hash: 'lleklrkelkj', }, { + ...DEFAULT_FIELDS[DataStream.BROWSER], __ui: { is_zip_url_tls_enabled: false, script_source: { @@ -609,6 +615,7 @@ const payloadData = [ 'url.port': null, urls: '', id: '', + hash: 'lleklrkelkj', }, ]; diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 890e4c8a5e4f1..7b850a44528fd 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -4970,6 +4970,15 @@ "properties": { "isCloudEnabled": { "type": "boolean" + }, + "trialEndDate": { + "type": "date" + }, + "inTrial": { + "type": "boolean" + }, + "isElasticStaffOwned": { + "type": "boolean" } } }, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index eba4c64dc818d..d4542ffa3c261 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -1918,7 +1918,6 @@ "discover.advancedSettings.discover.showFieldStatisticsDescription": "Activez le {fieldStatisticsDocs} pour afficher des détails tels que les valeurs minimale et maximale d'un champ numérique ou une carte d'un champ géographique. Cette fonctionnalité est en version bêta et susceptible d'être modifiée.", "discover.advancedSettings.discover.showMultifieldsDescription": "Détermine si les {multiFields} doivent s'afficher dans la fenêtre de document étendue. Dans la plupart des cas, les champs multiples sont les mêmes que les champs d'origine. Cette option est uniquement disponible lorsque le paramètre ''searchFieldsFromSource'' est désactivé.", "discover.advancedSettings.enableSQLDescription": "{technicalPreviewLabel} Cette fonctionnalité en préversion est encore très expérimentale, ne pas s'y fier pour les recherches ni pour les tableaux de bord en production. Ce paramètre désactive SQL comme langage de requête à base de texte dans Discover. Si vous avez des commentaires sur cette expérience, contactez-nous via {link}", - "discover.bucketIntervalTooltip": "Cet intervalle crée {bucketsDescription} pour permettre l’affichage dans la plage temporelle sélectionnée, il a donc été redimensionné vers {bucketIntervalDescription}.", "discover.context.contextOfTitle": "Les documents relatifs à #{anchorId}", "discover.context.newerDocumentsWarning": "Seuls {docCount} documents plus récents que le document ancré ont été trouvés.", "discover.context.olderDocumentsWarning": "Seuls {docCount} documents plus anciens que le document ancré ont été trouvés.", @@ -1956,19 +1955,15 @@ "discover.grid.filterForAria": "Filtrer sur cette {value}", "discover.grid.filterOutAria": "Exclure cette {value}", "discover.gridSampleSize.description": "Vous voyez les {sampleSize} premiers échantillons de documents qui correspondent à votre recherche. Pour modifier cette valeur, accédez à {advancedSettingsLink}.", - "discover.histogramTimeRangeIntervalDescription": "(intervalle : {value})", - "discover.hitsPluralTitle": "{formattedHits} {hits, plural, one {résultat} other {résultats}}", "discover.howToSeeOtherMatchingDocumentsDescription": "Voici les {sampleSize} premiers documents correspondant à votre recherche. Veuillez affiner celle-ci pour en voir plus.", "discover.noMatchRoute.bannerText": "L'application Discover ne reconnaît pas cet itinéraire : {route}", "discover.noResults.tryRemovingOrDisablingFilters": "Essayez de supprimer ou de {disablingFiltersLink}.", "discover.pageTitleWithSavedSearch": "Discover - {savedSearchTitle}", - "discover.partialHits": "≥ {formattedHits} {hits, plural, one {résultat} other {résultats}}", "discover.savedSearchAliasMatchRedirect.objectNoun": "Recherche {savedSearch}", "discover.savedSearchURLConflictCallout.objectNoun": "Recherche {savedSearch}", "discover.searchGenerationWithDescription": "Tableau généré par la recherche {searchTitle}", "discover.searchGenerationWithDescriptionGrid": "Tableau généré par la recherche {searchTitle} ({searchDescription})", "discover.selectedDocumentsNumber": "{nr} documents sélectionnés", - "discover.timeIntervalWithValue": "Intervalle de temps : {timeInterval}", "discover.topNav.optionsPopover.currentViewMode": "{viewModeLabel} : {currentViewMode}", "discover.utils.formatHit.moreFields": "et {count} {count, plural, one {autre champ} other {autres champs}}", "discover.valueIsNotConfiguredDataViewIDWarningTitle": "{stateVal} n'est pas un ID de vue de données configuré", @@ -2020,10 +2015,6 @@ "discover.backToTopLinkText": "Revenir en haut de la page.", "discover.badge.readOnly.text": "Lecture seule", "discover.badge.readOnly.tooltip": "Impossible d’enregistrer les recherches", - "discover.bucketIntervalTooltip.tooLargeBucketsText": "des compartiments trop volumineux", - "discover.bucketIntervalTooltip.tooManyBucketsText": "un trop grand nombre de compartiments", - "discover.chartOptions": "Options de graphique", - "discover.chartOptionsButton": "Options de graphique", "discover.clearSelection": "Effacer la sélection", "discover.context.breadcrumb": "Documents relatifs", "discover.context.failedToLoadAnchorDocumentDescription": "Échec de chargement du document ancré", @@ -2125,11 +2116,9 @@ "discover.dscTour.stepSort.description": "Utilisez le titre de colonne pour effectuer le tri sur un champ unique, ou la fenêtre contextuelle pour plusieurs champs.", "discover.dscTour.stepSort.imageAltText": "Cliquez sur un en-tête de colonne et sélectionnez l'ordre de tri souhaité. Ajustez un tri à champ multiple à l'aide de la fenêtre contextuelle des champs triés.", "discover.dscTour.stepSort.title": "Trier sur un ou plusieurs champs", - "discover.editVisualizationButton": "Modifier la visualisation", "discover.embeddable.inspectorRequestDataTitle": "Données", "discover.embeddable.inspectorRequestDescription": "Cette requête interroge Elasticsearch afin de récupérer les données pour la recherche.", "discover.embeddable.search.displayName": "rechercher", - "discover.errorLoadingChart": "Erreur lors du chargement du graphique", "discover.field.mappingConflict": "Ce champ est défini avec plusieurs types (chaîne, entier, etc.) dans les différents index qui correspondent à ce modèle. Vous pouvez toujours utiliser ce champ conflictuel, mais il sera indisponible pour les fonctions qui nécessitent que Kibana en connaisse le type. Pour corriger ce problème, vous devrez réindexer vos données.", "discover.field.mappingConflict.title": "Conflit de mapping", "discover.fieldChooser.addField.label": "Ajouter un champ", @@ -2233,10 +2222,6 @@ "discover.grid.viewDoc": "Afficher/Masquer les détails de la boîte de dialogue", "discover.gridSampleSize.advancedSettingsLinkLabel": "Paramètres avancés", "discover.helpMenu.appName": "Découverte", - "discover.hideChart": "Masquer le graphique", - "discover.histogramOfFoundDocumentsAriaLabel": "Histogramme des documents détectés", - "discover.histogramTimeRangeIntervalAuto": "Auto", - "discover.hitCountSpinnerAriaLabel": "Nombre final de résultats toujours en chargement", "discover.inspectorRequestDataTitleChart": "Données du graphique", "discover.inspectorRequestDataTitleDocuments": "Documents", "discover.inspectorRequestDataTitleTotalHits": "Nombre total de résultats", @@ -2245,7 +2230,6 @@ "discover.inspectorRequestDescriptionTotalHits": "Cette requête interroge Elasticsearch afin de récupérer le nombre total de résultats.", "discover.json.codeEditorAriaLabel": "Affichage JSON en lecture seule d’un document Elasticsearch", "discover.json.copyToClipboardLabel": "Copier dans le presse-papiers", - "discover.loadingChartResults": "Chargement du graphique", "discover.loadingDocuments": "Chargement des documents", "discover.loadingJSON": "Chargement de JSON", "discover.loadingResults": "Chargement des résultats", @@ -2294,7 +2278,6 @@ "discover.searchingTitle": "Recherche", "discover.selectColumnHeader": "Sélectionner la colonne", "discover.showAllDocuments": "Afficher tous les documents", - "discover.showChart": "Afficher le graphique", "discover.showErrorMessageAgain": "Afficher le message d'erreur", "discover.showSelectedDocumentsOnly": "Afficher uniquement les documents sélectionnés", "discover.singleDocRoute.errorTitle": "Une erreur s'est produite", @@ -2302,8 +2285,6 @@ "discover.sourceViewer.errorMessage": "Impossible de récupérer les données pour le moment. Actualisez l'onglet et réessayez.", "discover.sourceViewer.errorMessageTitle": "Une erreur s'est produite.", "discover.sourceViewer.refresh": "Actualiser", - "discover.timeIntervals": "Intervalles de temps", - "discover.timeIntervalWithValueWarning": "Avertissement", "discover.toggleSidebarAriaLabel": "Activer/Désactiver la barre latérale", "discover.topNav.openOptionsPopover.documentExplorerDisabledHint": "Saviez-vous que Discover possède un nouvel Explorateur de documents avec un meilleur tri des données, des colonnes redimensionnables et une vue en plein écran ? Vous pouvez modifier le mode d'affichage dans les Paramètres avancés.", "discover.topNav.openOptionsPopover.documentExplorerEnabledHint": "Vous pouvez revenir à l'affichage Discover classique dans les Paramètres avancés.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f5ef512297e2e..bbfd3a5f67903 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1916,7 +1916,6 @@ "discover.advancedSettings.discover.showFieldStatisticsDescription": "{fieldStatisticsDocs}を有効にすると、数値フィールドの最大/最小値やジオフィールドの地図といった詳細が表示されます。この機能はベータ段階で、変更される可能性があります。", "discover.advancedSettings.discover.showMultifieldsDescription": "拡張ドキュメントビューに{multiFields}が表示されるかどうかを制御します。ほとんどの場合、マルチフィールドは元のフィールドと同じです。「searchFieldsFromSource」がオフのときにのみこのオプションを使用できます。", "discover.advancedSettings.enableSQLDescription": "{technicalPreviewLabel} このパッチプレビュー機能は実験段階です。本番の保存された検索やダッシュボードでは、この機能を信頼しないでください。この設定により、Discoverでテキストベースのクエリ言語としてSQLを使用できます。このエクスペリエンスに関するフィードバックがございましたら、{link}からお問い合わせください", - "discover.bucketIntervalTooltip": "この間隔は選択された時間範囲に表示される{bucketsDescription}が作成されるため、{bucketIntervalDescription}にスケーリングされています。", "discover.context.contextOfTitle": "#{anchorId}の周りのドキュメント", "discover.context.newerDocumentsWarning": "アンカーよりも新しいドキュメントは{docCount}件しか見つかりませんでした。", "discover.context.olderDocumentsWarning": "アンカーよりも古いドキュメントは{docCount}件しか見つかりませんでした。", @@ -1952,19 +1951,15 @@ "discover.grid.filterForAria": "この{value}でフィルターを適用", "discover.grid.filterOutAria": "この{value}を除外", "discover.gridSampleSize.description": "検索と一致する最初の{sampleSize}ドキュメントを表示しています。この値を変更するには、{advancedSettingsLink}に移動してください。", - "discover.histogramTimeRangeIntervalDescription": "(間隔値: {value})", - "discover.hitsPluralTitle": "{formattedHits} {hits, plural, other {一致}}", "discover.howToSeeOtherMatchingDocumentsDescription": "これらは検索条件に一致した初めの {sampleSize} 件のドキュメントです。他の結果を表示するには検索条件を絞ってください。", "discover.noMatchRoute.bannerText": "Discoverアプリケーションはこのルート{route}を認識できません", "discover.noResults.tryRemovingOrDisablingFilters": "削除または{disablingFiltersLink}してください。", "discover.pageTitleWithSavedSearch": "Discover - {savedSearchTitle}", - "discover.partialHits": "≥{formattedHits} {hits, plural, other {一致}}", "discover.savedSearchAliasMatchRedirect.objectNoun": "{savedSearch}検索", "discover.savedSearchURLConflictCallout.objectNoun": "{savedSearch}検索", "discover.searchGenerationWithDescription": "検索{searchTitle}で生成されたテーブル", "discover.searchGenerationWithDescriptionGrid": "検索{searchTitle}で生成されたテーブル({searchDescription})", "discover.selectedDocumentsNumber": "{nr}個のドキュメントが選択されました", - "discover.timeIntervalWithValue": "時間間隔:{timeInterval}", "discover.topNav.optionsPopover.currentViewMode": "{viewModeLabel}: {currentViewMode}", "discover.utils.formatHit.moreFields": "および{count} more {count, plural, other {個のフィールド}}", "discover.valueIsNotConfiguredDataViewIDWarningTitle": "{stateVal}は設定されたデータビューIDではありません", @@ -2016,10 +2011,6 @@ "discover.backToTopLinkText": "最上部へ戻る。", "discover.badge.readOnly.text": "読み取り専用", "discover.badge.readOnly.tooltip": "検索を保存できません", - "discover.bucketIntervalTooltip.tooLargeBucketsText": "大きすぎるバケット", - "discover.bucketIntervalTooltip.tooManyBucketsText": "バケットが多すぎます", - "discover.chartOptions": "グラフオプション", - "discover.chartOptionsButton": "グラフオプション", "discover.clearSelection": "選択した項目をクリア", "discover.context.breadcrumb": "周りのドキュメント", "discover.context.failedToLoadAnchorDocumentDescription": "アンカードキュメントの読み込みに失敗しました", @@ -2121,11 +2112,9 @@ "discover.dscTour.stepSort.description": "列見出しを使用して1つのフィールドを並べ替えるか、複数のフィールドに対してポップオーバーを使用します。", "discover.dscTour.stepSort.imageAltText": "列見出しをクリックして、任意の並べ順を選択します。フィールドが並べ替えられたポップオーバーを使用して、複数のフィールドの並べ替えを調整します。", "discover.dscTour.stepSort.title": "1つ以上のフィールドを並べ替えます", - "discover.editVisualizationButton": "ビジュアライゼーションを編集", "discover.embeddable.inspectorRequestDataTitle": "データ", "discover.embeddable.inspectorRequestDescription": "このリクエストはElasticsearchにクエリをかけ、検索データを取得します。", "discover.embeddable.search.displayName": "検索", - "discover.errorLoadingChart": "グラフの読み込みエラー", "discover.field.mappingConflict": "このフィールドは、このパターンと一致するインデックス全体に対して複数の型(文字列、整数など)として定義されています。この競合フィールドを使用することはできますが、Kibana で型を認識する必要がある関数では使用できません。この問題を修正するにはデータのレンダリングが必要です。", "discover.field.mappingConflict.title": "マッピングの矛盾", "discover.fieldChooser.addField.label": "フィールドを追加", @@ -2229,10 +2218,6 @@ "discover.grid.viewDoc": "詳細ダイアログを切り替え", "discover.gridSampleSize.advancedSettingsLinkLabel": "高度な設定", "discover.helpMenu.appName": "Discover", - "discover.hideChart": "グラフを非表示", - "discover.histogramOfFoundDocumentsAriaLabel": "検出されたドキュメントのヒストグラム", - "discover.histogramTimeRangeIntervalAuto": "自動", - "discover.hitCountSpinnerAriaLabel": "読み込み中の最終一致件数", "discover.inspectorRequestDataTitleChart": "グラフデータ", "discover.inspectorRequestDataTitleDocuments": "ドキュメント", "discover.inspectorRequestDataTitleTotalHits": "総ヒット数", @@ -2241,7 +2226,6 @@ "discover.inspectorRequestDescriptionTotalHits": "このリクエストはElasticsearchにクエリをかけ、合計一致数を取得します。", "discover.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", "discover.json.copyToClipboardLabel": "クリップボードにコピー", - "discover.loadingChartResults": "グラフを読み込み中", "discover.loadingDocuments": "ドキュメントを読み込み中", "discover.loadingJSON": "JSONを読み込んでいます", "discover.loadingResults": "結果を読み込み中", @@ -2290,7 +2274,6 @@ "discover.searchingTitle": "検索中", "discover.selectColumnHeader": "列を選択", "discover.showAllDocuments": "すべてのドキュメントを表示", - "discover.showChart": "グラフを表示", "discover.showErrorMessageAgain": "エラーメッセージを表示", "discover.showSelectedDocumentsOnly": "選択したドキュメントのみを表示", "discover.singleDocRoute.errorTitle": "エラーが発生しました", @@ -2298,8 +2281,6 @@ "discover.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。", "discover.sourceViewer.errorMessageTitle": "エラーが発生しました", "discover.sourceViewer.refresh": "更新", - "discover.timeIntervals": "時間間隔", - "discover.timeIntervalWithValueWarning": "警告", "discover.toggleSidebarAriaLabel": "サイドバーを切り替える", "discover.topNav.openOptionsPopover.documentExplorerDisabledHint": "Discoverの新しいドキュメントエクスプローラーでは、データの並べ替え、列のサイズ変更、全画面表示といった優れた機能をご利用いただけます。高度な設定で表示モードを変更できます。", "discover.topNav.openOptionsPopover.documentExplorerEnabledHint": "高度な設定でクラシックDiscoverビューに戻すことができます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e4f966a0a485f..14c174124c67e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1918,7 +1918,6 @@ "discover.advancedSettings.discover.showFieldStatisticsDescription": "启用 {fieldStatisticsDocs} 以显示详细信息,如数字字段的最小和最大值,或地理字段的地图。此功能为公测版,可能会进行更改。", "discover.advancedSettings.discover.showMultifieldsDescription": "控制 {multiFields} 是否显示在展开的文档视图中。多数情况下,多字段与原始字段相同。此选项仅在 `searchFieldsFromSource` 关闭时可用。", "discover.advancedSettings.enableSQLDescription": "{technicalPreviewLabel} 此技术预览功能为高度实验性功能 -- 请勿在生产已保存搜索或仪表板中依赖此功能。此设置在 Discover 中将 SQL 用作基于文本的查询语言。\r\n如果具有与此体验有关的反馈,请通过 {link} 联系我们", - "discover.bucketIntervalTooltip": "此时间间隔创建的{bucketsDescription},无法在选定时间范围中显示,因此已调整为{bucketIntervalDescription}。", "discover.context.contextOfTitle": "#{anchorId} 周围的文档", "discover.context.newerDocumentsWarning": "仅可以找到 {docCount} 个比定位标记新的文档。", "discover.context.olderDocumentsWarning": "仅可以找到 {docCount} 个比定位标记旧的文档。", @@ -1956,19 +1955,15 @@ "discover.grid.filterForAria": "筛留此 {value}", "discover.grid.filterOutAria": "筛除此 {value}", "discover.gridSampleSize.description": "您正查看与您的搜索相匹配的前 {sampleSize} 个文档。要更改此值,请转到{advancedSettingsLink}。", - "discover.histogramTimeRangeIntervalDescription": "(时间间隔:{value})", - "discover.hitsPluralTitle": "{formattedHits} 个{hits, plural, other {命中}}", "discover.howToSeeOtherMatchingDocumentsDescription": "下面是与您的搜索匹配的前 {sampleSize} 个文档,请优化您的搜索以查看其他文档。", "discover.noMatchRoute.bannerText": "Discover 应用程序无法识别此路由:{route}", "discover.noResults.tryRemovingOrDisablingFilters": "尝试删除或{disablingFiltersLink}。", "discover.pageTitleWithSavedSearch": "Discover - {savedSearchTitle}", - "discover.partialHits": "≥{formattedHits} 个{hits, plural, other {命中}}", "discover.savedSearchAliasMatchRedirect.objectNoun": "{savedSearch} 搜索", "discover.savedSearchURLConflictCallout.objectNoun": "{savedSearch} 搜索", "discover.searchGenerationWithDescription": "搜索 {searchTitle} 生成的表", "discover.searchGenerationWithDescriptionGrid": "搜索 {searchTitle} 生成的表({searchDescription})", "discover.selectedDocumentsNumber": "{nr} 个文档已选择", - "discover.timeIntervalWithValue": "时间间隔:{timeInterval}", "discover.topNav.optionsPopover.currentViewMode": "{viewModeLabel}:{currentViewMode}", "discover.utils.formatHit.moreFields": "及另外 {count} 个{count, plural, other {字段}}", "discover.valueIsNotConfiguredDataViewIDWarningTitle": "{stateVal} 不是配置的数据视图 ID", @@ -2020,10 +2015,6 @@ "discover.backToTopLinkText": "返回顶部。", "discover.badge.readOnly.text": "只读", "discover.badge.readOnly.tooltip": "无法保存搜索", - "discover.bucketIntervalTooltip.tooLargeBucketsText": "存储桶过大", - "discover.bucketIntervalTooltip.tooManyBucketsText": "存储桶过多", - "discover.chartOptions": "图表选项", - "discover.chartOptionsButton": "图表选项", "discover.clearSelection": "清除所选内容", "discover.context.breadcrumb": "周围文档", "discover.context.failedToLoadAnchorDocumentDescription": "无法加载定位点文档", @@ -2125,11 +2116,9 @@ "discover.dscTour.stepSort.description": "使用列标题对单一字段进行排序,或使用弹出框对多个字段进行排序。", "discover.dscTour.stepSort.imageAltText": "单击列标题并选择所需排序顺序。使用字段排序弹出框调整多字段排序。", "discover.dscTour.stepSort.title": "对一个或多个字段排序", - "discover.editVisualizationButton": "编辑可视化", "discover.embeddable.inspectorRequestDataTitle": "数据", "discover.embeddable.inspectorRequestDescription": "此请求将查询 Elasticsearch 以获取搜索的数据。", "discover.embeddable.search.displayName": "搜索", - "discover.errorLoadingChart": "加载图表时出错", "discover.field.mappingConflict": "此字段在匹配此模式的各个索引中已定义为若干类型(字符串、整数等)。您可能仍可以使用此冲突字段,但它无法用于需要 Kibana 知道其类型的函数。要解决此问题,需要重新索引您的数据。", "discover.field.mappingConflict.title": "映射冲突", "discover.fieldChooser.addField.label": "添加字段", @@ -2233,10 +2222,6 @@ "discover.grid.viewDoc": "切换具有详情的对话框", "discover.gridSampleSize.advancedSettingsLinkLabel": "高级设置", "discover.helpMenu.appName": "Discover", - "discover.hideChart": "隐藏图表", - "discover.histogramOfFoundDocumentsAriaLabel": "已找到文档的直方图", - "discover.histogramTimeRangeIntervalAuto": "自动", - "discover.hitCountSpinnerAriaLabel": "最终命中计数仍在加载", "discover.inspectorRequestDataTitleChart": "图表数据", "discover.inspectorRequestDataTitleDocuments": "文档", "discover.inspectorRequestDataTitleTotalHits": "总命中数", @@ -2245,7 +2230,6 @@ "discover.inspectorRequestDescriptionTotalHits": "此请求将查询 Elasticsearch 以获取总命中数。", "discover.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", "discover.json.copyToClipboardLabel": "复制到剪贴板", - "discover.loadingChartResults": "正在加载图表", "discover.loadingDocuments": "正在加载文档", "discover.loadingJSON": "正在加载 JSON", "discover.loadingResults": "正在加载结果", @@ -2294,7 +2278,6 @@ "discover.searchingTitle": "正在搜索", "discover.selectColumnHeader": "选择列", "discover.showAllDocuments": "显示所有文档", - "discover.showChart": "显示图表", "discover.showErrorMessageAgain": "显示错误消息", "discover.showSelectedDocumentsOnly": "仅显示选定的文档", "discover.singleDocRoute.errorTitle": "发生错误", @@ -2302,8 +2285,6 @@ "discover.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。", "discover.sourceViewer.errorMessageTitle": "发生错误", "discover.sourceViewer.refresh": "刷新", - "discover.timeIntervals": "时间间隔", - "discover.timeIntervalWithValueWarning": "警告", "discover.toggleSidebarAriaLabel": "切换侧边栏", "discover.topNav.openOptionsPopover.documentExplorerDisabledHint": "您知道吗?Discover 有一种新的 Document Explorer,可提供更好的数据排序、可调整大小的列及全屏视图。您可以在高级设置中更改视图模式。", "discover.topNav.openOptionsPopover.documentExplorerEnabledHint": "您可以在高级设置中切换回经典 Discover 视图。", diff --git a/x-pack/test/api_integration/apis/uptime/rest/add_monitor_project.ts b/x-pack/test/api_integration/apis/uptime/rest/add_monitor_project.ts index 2be3509a61cf6..02a40be5d2f40 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/add_monitor_project.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/add_monitor_project.ts @@ -28,7 +28,7 @@ export default function ({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const security = getService('security'); const kibanaServer = getService('kibanaServer'); - const projectMonitorEndpoint = kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT; + const projectMonitorEndpoint = kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY; let projectMonitors: ProjectMonitorsRequest; let httpProjectMonitors: ProjectMonitorsRequest; @@ -194,6 +194,7 @@ export default function ({ getService }: FtrProviderContext) { 'url.port': null, urls: '', id: '', + hash: 'ekrjelkjrelkjre', }); } } finally { @@ -308,6 +309,7 @@ export default function ({ getService }: FtrProviderContext) { urls: Array.isArray(monitor.urls) ? monitor.urls?.[0] : monitor.urls, 'url.port': null, id: '', + hash: 'ekrjelkjrelkjre', }); } } finally { @@ -409,6 +411,7 @@ export default function ({ getService }: FtrProviderContext) { 'url.port': null, urls: '', id: '', + hash: 'ekrjelkjrelkjre', }); } } finally { @@ -511,6 +514,7 @@ export default function ({ getService }: FtrProviderContext) { ? monitor.wait?.slice(0, -1) : `${parseInt(monitor.wait?.slice(0, -1) || '1', 10) * 60}`, id: '', + hash: 'ekrjelkjrelkjre', }); } } finally { @@ -547,7 +551,7 @@ export default function ({ getService }: FtrProviderContext) { it('project monitors - returns a list of successfully updated monitors', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); @@ -575,12 +579,12 @@ export default function ({ getService }: FtrProviderContext) { it('project monitors - does not increment monitor revision unless a change has been made', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); @@ -609,7 +613,7 @@ export default function ({ getService }: FtrProviderContext) { it('project monitors - increments monitor revision when a change has been made', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); @@ -655,7 +659,7 @@ export default function ({ getService }: FtrProviderContext) { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -701,7 +705,7 @@ export default function ({ getService }: FtrProviderContext) { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -839,7 +843,8 @@ export default function ({ getService }: FtrProviderContext) { } ); - const spaceUrl = kibanaServerUrl + `/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT}`; + const spaceUrl = + kibanaServerUrl + `/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY}`; const messages = await parseStreamApiResponse( spaceUrl, @@ -928,6 +933,7 @@ export default function ({ getService }: FtrProviderContext) { upload: 3, }, type: 'browser', + hash: 'ekrjelkjrelkjre', }, reason: 'Failed to save or update monitor. Configuration is not valid', }, @@ -966,7 +972,7 @@ export default function ({ getService }: FtrProviderContext) { full_name: 'a kibana user', }); await supertestWithoutAuth - .put(`/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT}`) + .put(`/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY}`) .auth(username, password) .set('kbn-xsrf', 'true') .send(projectMonitors) @@ -1020,7 +1026,7 @@ export default function ({ getService }: FtrProviderContext) { full_name: 'a kibana user', }); await supertestWithoutAuth - .put(`/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT}`) + .put(`/s/${SPACE_ID}${API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY}`) .auth(username, password) .set('kbn-xsrf', 'true') .send(projectMonitors) @@ -1055,7 +1061,7 @@ export default function ({ getService }: FtrProviderContext) { it('project monitors - is able to decrypt monitor when updated after hydration', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); @@ -1109,12 +1115,12 @@ export default function ({ getService }: FtrProviderContext) { it('project monitors - is able to enable and disable monitors', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(projectMonitors); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1172,7 +1178,7 @@ export default function ({ getService }: FtrProviderContext) { }); const messages = await parseStreamApiResponse( - kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT, + kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY, JSON.stringify({ ...projectMonitors, keep_stale: false, @@ -1219,6 +1225,7 @@ export default function ({ getService }: FtrProviderContext) { latency: 20, upload: 3, }, + hash: 'ekrjelkjrelkjre', }, reason: 'Failed to create or update monitor', }, @@ -1270,7 +1277,7 @@ export default function ({ getService }: FtrProviderContext) { }); await parseStreamApiResponse( - kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT, + kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY, JSON.stringify({ ...projectMonitors, keep_stale: false, @@ -1279,7 +1286,7 @@ export default function ({ getService }: FtrProviderContext) { ); const messages = await parseStreamApiResponse( - kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT, + kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY, JSON.stringify({ ...projectMonitors, keep_stale: false, @@ -1315,7 +1322,7 @@ export default function ({ getService }: FtrProviderContext) { }); const messages2 = await parseStreamApiResponse( - kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT, + kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY, JSON.stringify({ ...projectMonitors, keep_stale: false, @@ -1418,7 +1425,7 @@ export default function ({ getService }: FtrProviderContext) { it('creates integration policies for project monitors with private locations', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1482,7 +1489,7 @@ export default function ({ getService }: FtrProviderContext) { }; try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(monitorRequest); @@ -1509,7 +1516,7 @@ export default function ({ getService }: FtrProviderContext) { expect(packagePolicy.policy_id).eql(testPolicyId); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...monitorRequest, @@ -1537,7 +1544,7 @@ export default function ({ getService }: FtrProviderContext) { it('deletes integration policies for project monitors when private location is removed from the monitor', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1582,7 +1589,7 @@ export default function ({ getService }: FtrProviderContext) { ); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1615,7 +1622,7 @@ export default function ({ getService }: FtrProviderContext) { it('deletes integration policies when project monitors are deleted', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1661,7 +1668,7 @@ export default function ({ getService }: FtrProviderContext) { ); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1715,7 +1722,7 @@ export default function ({ getService }: FtrProviderContext) { }; try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send(monitorRequest); @@ -1849,7 +1856,7 @@ export default function ({ getService }: FtrProviderContext) { }); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...monitorRequest, @@ -1882,7 +1889,7 @@ export default function ({ getService }: FtrProviderContext) { it('handles updating package policies when project monitors are updated', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1927,7 +1934,7 @@ export default function ({ getService }: FtrProviderContext) { ); await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -1974,7 +1981,7 @@ export default function ({ getService }: FtrProviderContext) { it('handles location formatting for both private and public locations', async () => { try { await supertest - .put(API_URLS.SYNTHETICS_MONITORS_PROJECT) + .put(API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY) .set('kbn-xsrf', 'true') .send({ ...projectMonitors, @@ -2082,7 +2089,7 @@ type StreamApiFunction = ( * This helps the test file have DRY code when it comes to calling * the same streaming endpoint over and over by defining some selective defaults. */ -const parseStreamApiResponse: StreamApiFunction> = async ( +export const parseStreamApiResponse: StreamApiFunction> = async ( url: string, body?: BodyInit, extraHeaders?: HeadersInit, diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/browser_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/browser_monitor.json index 0d1508bf780cc..1ec38eaf7633f 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/browser_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/browser_monitor.json @@ -48,5 +48,6 @@ "form_monitor_type": "multistep", "urls": "", "url.port": null, - "id": "" + "id": "", + "hash": "" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json index 2f68e70f0e00d..218cc5b1b9770 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/http_monitor.json @@ -80,5 +80,6 @@ "origin": "ui", "form_monitor_type": "http", "journey_id": "", - "id": "" + "id": "", + "hash": "" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/icmp_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/icmp_monitor.json index fb6efa3a604d2..2e0c25085ec65 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/icmp_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/icmp_monitor.json @@ -20,5 +20,6 @@ "namespace": "testnamespace", "origin": "ui", "form_monitor_type": "icmp", - "id": "" + "id": "", + "hash": "" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_browser_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_browser_monitor.json index ba1101be34ba4..eb51f1fa4bf18 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_browser_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_browser_monitor.json @@ -22,6 +22,7 @@ "content": "UEsDBBQACAAIAON5qVQAAAAAAAAAAAAAAAAfAAAAZXhhbXBsZXMvdG9kb3MvYmFzaWMuam91cm5leS50c22Q0WrDMAxF3/sVF7MHB0LMXlc6RvcN+wDPVWNviW0sdUsp/fe5SSiD7UFCWFfHujIGlpnkybwxFTZfoY/E3hsaLEtwhs9RPNWKDU12zAOxkXRIbN4tB9d9pFOJdO6EN2HMqQguWN9asFBuQVMmJ7jiWNII9fIXrbabdUYr58l9IhwhQQZCYORCTFFUC31Btj21NRc7Mq4Nds+4bDD/pNVgT9F52Jyr2Fa+g75LAPttg8yErk+S9ELpTmVotlVwnfNCuh2lepl3+JflUmSBJ3uggt1v9INW/lHNLKze9dJe1J3QJK8pSvWkm6aTtCet5puq+x63+AFQSwcIAPQ3VfcAAACcAQAAUEsBAi0DFAAIAAgA43mpVAD0N1X3AAAAnAEAAB8AAAAAAAAAAAAgAKSBAAAAAGV4YW1wbGVzL3RvZG9zL2Jhc2ljLmpvdXJuZXkudHNQSwUGAAAAAAEAAQBNAAAARAEAAAAA", "filter": { "match": "check if title is present" - } + }, + "hash": "ekrjelkjrelkjre" }] } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_http_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_http_monitor.json index 42044c8ba9cf3..5d2a3b9ff8eb5 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_http_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_http_monitor.json @@ -35,7 +35,8 @@ }, "unsupportedKey": { "nestedUnsupportedKey": "unsupportedValue" - } + }, + "hash": "ekrjelkjrelkjre" }, { "locations": ["localhost"], @@ -69,7 +70,8 @@ "saved" ] } - } + }, + "hash": "ekrjelkjrelkjre" } ] } \ No newline at end of file diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_icmp_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_icmp_monitor.json index b19e910882582..f7dcb917b621d 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_icmp_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_icmp_monitor.json @@ -14,7 +14,8 @@ "schedule": 1, "tags": [ "service:smtp", "org:google" ], "privateLocations": [ "Test private location 0" ], - "wait": "30s" + "wait": "30s", + "hash": "ekrjelkjrelkjre" }, { "locations": [ "localhost" ], @@ -25,7 +26,8 @@ "schedule": 1, "tags": "tag1,tag2", "privateLocations": [ "Test private location 0" ], - "wait": "1m" + "wait": "1m", + "hash": "ekrjelkjrelkjre" }, { "locations": [ "localhost" ], @@ -38,7 +40,8 @@ "privateLocations": [ "Test private location 0" ], "unsupportedKey": { "nestedUnsupportedKey": "unnsuportedValue" - } + }, + "hash": "ekrjelkjrelkjre" } ] } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_tcp_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_tcp_monitor.json index 82d6c8c557e77..5d028f447ba0a 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_tcp_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/project_tcp_monitor.json @@ -10,7 +10,8 @@ "hosts": [ "smtp.gmail.com:587" ], "schedule": 1, "tags": [ "service:smtp", "org:google" ], - "privateLocations": [ "BEEP" ] + "privateLocations": [ "BEEP" ], + "hash": "ekrjelkjrelkjre" }, { "locations": [ "localhost" ], @@ -20,7 +21,8 @@ "hosts": "localhost:18278", "schedule": 1, "tags": "tag1,tag2", - "privateLocations": [ "BEEP" ] + "privateLocations": [ "BEEP" ], + "hash": "ekrjelkjrelkjre" }, { "locations": [ "localhost" ], @@ -34,7 +36,8 @@ "privateLocations": [ "BEEP" ], "unsupportedKey": { "nestedUnsupportedKey": "unnsuportedValue" - } + }, + "hash": "ekrjelkjrelkjre" } ] } diff --git a/x-pack/test/api_integration/apis/uptime/rest/fixtures/tcp_monitor.json b/x-pack/test/api_integration/apis/uptime/rest/fixtures/tcp_monitor.json index bfa0b3a1a7242..209ef89373736 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/fixtures/tcp_monitor.json +++ b/x-pack/test/api_integration/apis/uptime/rest/fixtures/tcp_monitor.json @@ -34,5 +34,6 @@ "namespace": "testnamespace", "origin": "ui", "form_monitor_type": "tcp", - "id": "" + "id": "", + "hash": "" } diff --git a/x-pack/test/api_integration/apis/uptime/rest/get_monitor_project.ts b/x-pack/test/api_integration/apis/uptime/rest/get_monitor_project.ts new file mode 100644 index 0000000000000..bbd0715c45739 --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/rest/get_monitor_project.ts @@ -0,0 +1,440 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import uuid from 'uuid'; +import expect from '@kbn/expect'; +import type SuperTest from 'supertest'; +import { format as formatUrl } from 'url'; +import { + ProjectMonitorsRequest, + ProjectMonitor, + ProjectMonitorMetaData, +} from '@kbn/synthetics-plugin/common/runtime_types'; +import { API_URLS } from '@kbn/synthetics-plugin/common/constants'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { getFixtureJson } from './helper/get_fixture_json'; +import { PrivateLocationTestService } from './services/private_location_test_service'; +import { parseStreamApiResponse } from './add_monitor_project'; + +export default function ({ getService }: FtrProviderContext) { + describe('GetProjectMonitors', function () { + this.tags('skipCloud'); + + const supertest = getService('supertest'); + const config = getService('config'); + const kibanaServerUrl = formatUrl(config.get('servers.kibana')); + const projectMonitorEndpoint = kibanaServerUrl + API_URLS.SYNTHETICS_MONITORS_PROJECT_LEGACY; + + let projectMonitors: ProjectMonitorsRequest; + let httpProjectMonitors: ProjectMonitorsRequest; + let tcpProjectMonitors: ProjectMonitorsRequest; + let icmpProjectMonitors: ProjectMonitorsRequest; + + let testPolicyId = ''; + const testPrivateLocations = new PrivateLocationTestService(getService); + + const setUniqueIds = (request: ProjectMonitorsRequest) => { + return { + ...request, + monitors: request.monitors.map((monitor) => ({ ...monitor, id: uuid.v4() })), + }; + }; + + before(async () => { + await supertest.post('/api/fleet/setup').set('kbn-xsrf', 'true').send().expect(200); + await supertest + .post('/api/fleet/epm/packages/synthetics/0.10.3') + .set('kbn-xsrf', 'true') + .send({ force: true }) + .expect(200); + + const testPolicyName = 'Fleet test server policy' + Date.now(); + const apiResponse = await testPrivateLocations.addFleetPolicy(testPolicyName); + testPolicyId = apiResponse.body.item.id; + await testPrivateLocations.setTestLocations([testPolicyId]); + }); + + beforeEach(() => { + projectMonitors = setUniqueIds(getFixtureJson('project_browser_monitor')); + httpProjectMonitors = setUniqueIds(getFixtureJson('project_http_monitor')); + tcpProjectMonitors = setUniqueIds(getFixtureJson('project_tcp_monitor')); + icmpProjectMonitors = setUniqueIds(getFixtureJson('project_icmp_monitor')); + }); + + it('project monitors - fetches all monitors - browser', async () => { + const monitors = []; + const project = 'test-brower-suite'; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...projectMonitors.monitors[0], + id: `test browser id ${i}`, + name: `test name ${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + monitors, + }) + ); + + const firstPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const { monitors: firstPageMonitors, total, after_key: afterKey } = firstPageResponse.body; + expect(firstPageMonitors.length).to.eql(500); + expect(total).to.eql(600); + expect(afterKey).to.eql('test browser id 548'); + + const secondPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .query({ + search_after: afterKey, + }) + .send() + .expect(200); + const { monitors: secondPageMonitors } = secondPageResponse.body; + expect(secondPageMonitors.length).to.eql(100); + checkFields([...firstPageMonitors, ...secondPageMonitors], monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + keep_stale: false, + monitors: [], + }) + ); + } + }); + + it('project monitors - fetches all monitors - http', async () => { + const monitors = []; + const project = 'test-http-suite'; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...httpProjectMonitors.monitors[1], + id: `test http id ${i}`, + name: `test name ${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + monitors, + }) + ); + + const firstPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const { + monitors: firstPageProjectMonitors, + after_key: afterKey, + total, + } = firstPageResponse.body; + expect(firstPageProjectMonitors.length).to.eql(500); + expect(total).to.eql(600); + expect(afterKey).to.eql('test http id 548'); + + const secondPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .query({ + search_after: afterKey, + }) + .send() + .expect(200); + const { monitors: secondPageProjectMonitors } = secondPageResponse.body; + expect(secondPageProjectMonitors.length).to.eql(100); + checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + keep_stale: false, + monitors: [], + }) + ); + } + }); + + it('project monitors - fetches all monitors - tcp', async () => { + const monitors = []; + const project = 'test-tcp-suite'; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...tcpProjectMonitors.monitors[0], + id: `test tcp id ${i}`, + name: `test name ${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + monitors, + }) + ); + + const firstPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const { + monitors: firstPageProjectMonitors, + after_key: afterKey, + total, + } = firstPageResponse.body; + expect(firstPageProjectMonitors.length).to.eql(500); + expect(total).to.eql(600); + expect(afterKey).to.eql('test tcp id 548'); + + const secondPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .query({ + search_after: afterKey, + }) + .send() + .expect(200); + const { monitors: secondPageProjectMonitors } = secondPageResponse.body; + expect(secondPageProjectMonitors.length).to.eql(100); + checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + keep_stale: false, + monitors: [], + }) + ); + } + }); + + it('project monitors - fetches all monitors - icmp', async () => { + const monitors = []; + const project = 'test-icmp-suite'; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...icmpProjectMonitors.monitors[0], + id: `test icmp id ${i}`, + name: `test name ${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + monitors, + }) + ); + + const firstPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const { + monitors: firstPageProjectMonitors, + after_key: afterKey, + total, + } = firstPageResponse.body; + expect(firstPageProjectMonitors.length).to.eql(500); + expect(total).to.eql(600); + expect(afterKey).to.eql('test icmp id 548'); + + const secondPageResponse = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', project)) + .set('kbn-xsrf', 'true') + .query({ + search_after: afterKey, + }) + .send() + .expect(200); + const { monitors: secondPageProjectMonitors } = secondPageResponse.body; + expect(secondPageProjectMonitors.length).to.eql(100); + + checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project, + keep_stale: false, + monitors: [], + }) + ); + } + }); + + it('project monitors - handles url ecoded project names', async () => { + const monitors = []; + const projectName = 'Test project'; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...icmpProjectMonitors.monitors[0], + id: `test url id ${i}`, + name: `test name ${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project: projectName, + keep_stale: false, + monitors, + }) + ); + + const firstPageResponse = await supertest + .get( + API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', encodeURI(projectName)) + ) + .set('kbn-xsrf', 'true') + .send() + .expect(200); + + const { + monitors: firstPageProjectMonitors, + after_key: afterKey, + total, + } = firstPageResponse.body; + expect(firstPageProjectMonitors.length).to.eql(500); + expect(total).to.eql(600); + expect(afterKey).to.eql('test url id 548'); + + const secondPageResponse = await supertest + .get( + API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', encodeURI(projectName)) + ) + .set('kbn-xsrf', 'true') + .query({ + search_after: afterKey, + }) + .send() + .expect(200); + const { monitors: secondPageProjectMonitors } = secondPageResponse.body; + expect(secondPageProjectMonitors.length).to.eql(100); + + checkFields([...firstPageProjectMonitors, ...secondPageProjectMonitors], monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + project: projectName, + keep_stale: false, + monitors: [], + }) + ); + } + }); + + it('project monitors - handles per_page parameter', async () => { + const monitors = []; + const perPage = 250; + for (let i = 0; i < 600; i++) { + monitors.push({ + ...icmpProjectMonitors.monitors[0], + id: `test-id-${i}`, + name: `test-name-${i}`, + }); + } + + try { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + monitors, + }) + ); + let count = Number.MAX_VALUE; + let afterId; + const fullResponse: ProjectMonitorMetaData[] = []; + let page = 1; + while (count >= 250) { + const response: SuperTest.Response = await supertest + .get(API_URLS.SYNTHETICS_MONITORS_PROJECT.replace('{projectName}', 'test-suite')) + .set('kbn-xsrf', 'true') + .query({ + per_page: perPage, + search_after: afterId, + }) + .send() + .expect(200); + + const { monitors: monitorsResponse, after_key: afterKey, total } = response.body; + expect(total).to.eql(600); + count = monitorsResponse.length; + fullResponse.push(...monitorsResponse); + if (page < 3) { + expect(count).to.eql(perPage); + } else { + expect(count).to.eql(100); + } + page++; + + afterId = afterKey; + } + // expect(fullResponse.length).to.eql(600); + // checkFields(fullResponse, monitors); + } finally { + await parseStreamApiResponse( + projectMonitorEndpoint, + JSON.stringify({ + ...projectMonitors, + keep_stale: false, + monitors: [], + }) + ); + } + }); + }); +} + +const checkFields = (monitorMetaData: ProjectMonitorMetaData[], monitors: ProjectMonitor[]) => { + monitors.forEach((monitor) => { + const configIsCorrect = monitorMetaData.some((ndjson: Record) => { + return ndjson.journey_id === monitor.id && ndjson.hash === monitor.hash; + }); + expect(configIsCorrect).to.eql(true); + }); +}; diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts index dfd1b3baffc5e..e1fd22c2baf8a 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -78,6 +78,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./get_monitor_overview')); loadTestFile(require.resolve('./add_monitor')); loadTestFile(require.resolve('./add_monitor_project')); + loadTestFile(require.resolve('./get_monitor_project')); loadTestFile(require.resolve('./add_monitor_private_location')); loadTestFile(require.resolve('./edit_monitor')); loadTestFile(require.resolve('./delete_monitor')); diff --git a/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts b/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts index a2a44e7d086da..470a68aeacc19 100644 --- a/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts +++ b/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts @@ -58,13 +58,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); } - function fetchTraces(samples: Array<{ traceId: string; transactionId: string }>) { - if (!samples.length) { + function fetchTraces(traceSamples: Array<{ traceId: string; transactionId: string }>) { + if (!traceSamples.length) { return []; } return Promise.all( - samples.map(async ({ traceId }) => { + traceSamples.map(async ({ traceId }) => { const response = await apmApiClient.readUser({ endpoint: `GET /internal/apm/traces/{traceId}`, params: { @@ -90,7 +90,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expect(response.body).to.eql({ - samples: [], + traceSamples: [], }); }); }); @@ -168,28 +168,28 @@ export default function ApiTest({ getService }: FtrProviderContext) { describe('and the query is empty', () => { it('returns all trace samples', async () => { const { - body: { samples }, + body: { traceSamples }, } = await fetchTraceSamples({ query: '', type: TraceSearchType.kql, environment: 'ENVIRONMENT_ALL', }); - expect(samples.length).to.eql(5); + expect(traceSamples.length).to.eql(5); }); }); describe('and query is set', () => { it('returns the relevant traces', async () => { const { - body: { samples }, + body: { traceSamples }, } = await fetchTraceSamples({ query: 'span.destination.service.resource:elasticsearch', type: TraceSearchType.kql, environment: 'ENVIRONMENT_ALL', }); - expect(samples.length).to.eql(1); + expect(traceSamples.length).to.eql(1); }); }); }); @@ -214,7 +214,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { describe('and the query is set', () => { it('returns the correct trace samples for transaction sequences', async () => { const { - body: { samples }, + body: { traceSamples }, } = await fetchTraceSamples({ query: `sequence by trace.id [ transaction where service.name == "java" ] @@ -223,7 +223,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { environment: 'ENVIRONMENT_ALL', }); - const traces = await fetchTraces(samples); + const traces = await fetchTraces(traceSamples); expect(traces.length).to.eql(2); @@ -242,7 +242,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('returns the correct trace samples for join sequences', async () => { const { - body: { samples }, + body: { traceSamples }, } = await fetchTraceSamples({ query: `sequence by trace.id [ span where service.name == "java" ] by span.id @@ -251,7 +251,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { environment: 'ENVIRONMENT_ALL', }); - const traces = await fetchTraces(samples); + const traces = await fetchTraces(traceSamples); expect(traces.length).to.eql(1); @@ -266,7 +266,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('returns the correct trace samples for exit spans', async () => { const { - body: { samples }, + body: { traceSamples }, } = await fetchTraceSamples({ query: `sequence by trace.id [ transaction where service.name == "python" ] @@ -275,7 +275,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { environment: 'ENVIRONMENT_ALL', }); - const traces = await fetchTraces(samples); + const traces = await fetchTraces(traceSamples); expect(traces.length).to.eql(1); diff --git a/x-pack/test/common/lib/test_data_loader.ts b/x-pack/test/common/lib/test_data_loader.ts index 61c8ff4c1bf52..64a69a5ac8170 100644 --- a/x-pack/test/common/lib/test_data_loader.ts +++ b/x-pack/test/common/lib/test_data_loader.ts @@ -68,6 +68,7 @@ export function getTestDataLoader({ getService }) { const kbnServer = getService('kibanaServer'); const supertest = getService('supertest'); const log = getService('log'); + const es = getService('es'); return { createFtrSpaces: async () => { @@ -124,5 +125,28 @@ export function getTestDataLoader({ getService }) { ]) ); }, + + deleteAllSavedObjectsFromKibanaIndex: async () => { + await es.deleteByQuery({ + index: '.kibana', + wait_for_completion: true, + body: { + conflicts: 'proceed', + query: { + bool: { + must_not: [ + { + term: { + type: { + value: 'space', + }, + }, + }, + ], + }, + }, + }, + }); + }, }; } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts index 3f9394f2e2b5a..dea6703d2fef4 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts @@ -46,7 +46,7 @@ export default ({ getService }: FtrProviderContext) => { // Note: We don't actually find signals well with ML tests at the moment so there are not tests for ML rule type for telemetry // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/132856 - describe.skip('Detection rule status telemetry', async () => { + describe('Detection rule status telemetry', async () => { before(async () => { // Just in case other tests do not clean up the event logs, let us clear them now and here only once. await deleteAllEventLogExecutionEvents(es, log); @@ -209,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { expect(stats?.detection_rules.detection_rule_status.custom_rules.query.succeeded).to.eql(1); }); - it('should have non zero values for "succeeded", "index_duration", and "search_duration"', () => { + it('should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.query.index_duration.max ).to.be.above(1); @@ -228,6 +228,15 @@ export default ({ getService }: FtrProviderContext) => { expect( stats?.detection_rules.detection_rule_status.custom_rules.query.search_duration.min ).to.be.above(1); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.query.enrichment_duration.max + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.query.enrichment_duration.avg + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.query.enrichment_duration.min + ).to.be.above(0); }); it('should have a total value for "detection_rule_status.custom_rules" rule ', () => { @@ -387,7 +396,7 @@ export default ({ getService }: FtrProviderContext) => { expect(stats?.detection_rules.detection_rule_status.custom_rules.eql.succeeded).to.eql(1); }); - it('should have non zero values for "succeeded", "index_duration", and "search_duration"', () => { + it('should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.eql.index_duration.max ).to.be.above(1); @@ -406,6 +415,15 @@ export default ({ getService }: FtrProviderContext) => { expect( stats?.detection_rules.detection_rule_status.custom_rules.eql.search_duration.min ).to.be.above(1); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.eql.enrichment_duration.max + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.eql.enrichment_duration.avg + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.eql.enrichment_duration.min + ).to.be.above(0); }); it('should have a total value for "detection_rule_status.custom_rules" rule ', () => { @@ -575,7 +593,7 @@ export default ({ getService }: FtrProviderContext) => { ).to.eql(1); }); - it('should have non zero values for "succeeded", "index_duration", and "search_duration"', () => { + it('should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.threshold.index_duration.max ).to.be.above(1); @@ -594,6 +612,18 @@ export default ({ getService }: FtrProviderContext) => { expect( stats?.detection_rules.detection_rule_status.custom_rules.threshold.search_duration.min ).to.be.above(1); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threshold.enrichment_duration + .max + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threshold.enrichment_duration + .avg + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threshold.enrichment_duration + .min + ).to.be.above(0); }); it('should have a total value for "detection_rule_status.custom_rules" rule ', () => { @@ -772,7 +802,7 @@ export default ({ getService }: FtrProviderContext) => { ).to.eql(1); }); - it('should have non zero values for "succeeded", "index_duration", and "search_duration"', () => { + it('should have non zero values for "succeeded", "index_duration", "search_duration" and "enrichment_duration"', () => { expect( stats?.detection_rules.detection_rule_status.custom_rules.threat_match.index_duration.max ).to.be.above(1); @@ -791,6 +821,18 @@ export default ({ getService }: FtrProviderContext) => { expect( stats?.detection_rules.detection_rule_status.custom_rules.threat_match.search_duration.min ).to.be.above(1); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threat_match.enrichment_duration + .max + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threat_match.enrichment_duration + .avg + ).to.be.above(0); + expect( + stats?.detection_rules.detection_rule_status.custom_rules.threat_match.enrichment_duration + .min + ).to.be.above(0); }); it('should have a total value for "detection_rule_status.custom_rules" rule ', () => { diff --git a/x-pack/test/functional/apps/discover/visualize_field.ts b/x-pack/test/functional/apps/discover/visualize_field.ts index be1f223110503..453c3467c923a 100644 --- a/x-pack/test/functional/apps/discover/visualize_field.ts +++ b/x-pack/test/functional/apps/discover/visualize_field.ts @@ -95,7 +95,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.discover.createAdHocDataView('logst', true); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.click('discoverEditVisualization'); + await testSubjects.click('unifiedHistogramEditVisualization'); await PageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async () => { diff --git a/x-pack/test/functional/apps/lens/group1/ad_hoc_data_view.ts b/x-pack/test/functional/apps/lens/group1/ad_hoc_data_view.ts index e70e4b59dc31d..2ea778c2b8d7f 100644 --- a/x-pack/test/functional/apps/lens/group1/ad_hoc_data_view.ts +++ b/x-pack/test/functional/apps/lens/group1/ad_hoc_data_view.ts @@ -162,7 +162,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ).getVisibleText(); expect(actualIndexPattern).to.be('*stash*'); - const actualDiscoverQueryHits = await testSubjects.getVisibleText('discoverQueryHits'); + const actualDiscoverQueryHits = await testSubjects.getVisibleText( + 'unifiedHistogramQueryHits' + ); expect(actualDiscoverQueryHits).to.be('14,005'); const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); diff --git a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts index ab9b08104a8e7..29f684c1ebf37 100644 --- a/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts @@ -41,7 +41,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); // check the table columns const columns = await PageObjects.discover.getColumnHeaders(); expect(columns).to.eql(['extension.raw', '@timestamp', 'bytes']); @@ -67,7 +67,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const [lensWindowHandler, discoverWindowHandle] = await browser.getAllWindowHandles(); await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); expect(await queryBar.getQueryString()).be.eql(''); await browser.closeCurrentWindow(); await browser.switchToWindow(lensWindowHandler); @@ -103,7 +103,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const [lensWindowHandler, discoverWindowHandle] = await browser.getAllWindowHandles(); await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); // check the query expect(await queryBar.getQueryString()).be.eql( '( ( extension.raw: "png" ) OR ( extension.raw: "css" ) OR ( extension.raw: "jpg" ) )' @@ -139,7 +139,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const [lensWindowHandler, discoverWindowHandle] = await browser.getAllWindowHandles(); await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); // check the columns const columns = await PageObjects.discover.getColumnHeaders(); expect(columns).to.eql(['extension.raw', '@timestamp', 'memory']); @@ -174,7 +174,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const [lensWindowHandler, discoverWindowHandle] = await browser.getAllWindowHandles(); await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); // check the query expect(await queryBar.getQueryString()).be.eql( diff --git a/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts index 92e9b6fcdb58e..a89b4c8727bc1 100644 --- a/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts @@ -47,7 +47,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail('discoverChart'); + await testSubjects.existOrFail('unifiedHistogramChart'); // check the table columns const columns = await PageObjects.discover.getColumnHeaders(); expect(columns).to.eql(['ip', '@timestamp', 'bytes']); diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/metric.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/metric.ts index caeeb5c935d85..759b91a6e3843 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/metric.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/metric.ts @@ -9,7 +9,16 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { visualize, lens, timePicker } = getPageObjects(['visualize', 'lens', 'timePicker']); + const { visEditor, visualize, lens, timePicker, visChart } = getPageObjects([ + 'visEditor', + 'visualize', + 'visChart', + 'lens', + 'timePicker', + ]); + + const testSubjects = getService('testSubjects'); + const find = getService('find'); describe('Metric', function describeIndexTests() { const isNewChartsLibraryEnabled = true; @@ -44,5 +53,165 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }, ]); }); + + it('should convert aggregation with params', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Average', 'metrics'); + await visEditor.selectField('machine.ram', 'metrics'); + await visEditor.clickGo(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + + expect(await lens.getLayerCount()).to.be(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(1); + expect(await dimensions[0].getVisibleText()).to.be('Average machine.ram'); + + expect((await lens.getMetricVisualizationData()).length).to.be.equal(1); + expect(await lens.getMetricVisualizationData()).to.eql([ + { + title: 'Average machine.ram', + subtitle: undefined, + extraText: '', + value: '13.1B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + ]); + }); + + it('should convert sibling pipeline aggregation', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Max Bucket', 'metrics'); + await visEditor.clickGo(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + + expect(await lens.getLayerCount()).to.be(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(await dimensions[0].getVisibleText()).to.be('Overall Max of Count'); + expect(await dimensions[1].getVisibleText()).to.be('@timestamp'); + + expect((await lens.getMetricVisualizationData()).length).to.be.equal(1); + expect(await lens.getMetricVisualizationData()).to.eql([ + { + title: 'Overall Max of Count', + subtitle: undefined, + extraText: '', + value: '1.44K', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + ]); + }); + + it('should not convert aggregation with not supported field type', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Top metrics', 'metrics'); + await visEditor.selectField('extension.raw', 'metrics'); + + await visEditor.clickGo(); + + const button = await testSubjects.exists('visualizeEditInLensButton'); + expect(button).to.be(false); + }); + + it('should convert color ranges', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Average', 'metrics'); + await visEditor.selectField('machine.ram', 'metrics'); + await visEditor.clickBucket('Split group'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + + await visEditor.clickOptionsTab(); + await testSubjects.setValue('metricColorRange0__to', '10000'); + await testSubjects.click('metricColorRange__addRangeButton'); + + await testSubjects.setValue('metricColorRange1__to', '20000'); + await visChart.waitForVisualizationRenderingStabilized(); + + const backgroundButton = await find.byCssSelector('[data-text="Background"]'); + await backgroundButton.click(); + await visEditor.clickGo(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + + expect(await lens.getLayerCount()).to.be(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(await dimensions[0].getVisibleText()).to.be('Average machine.ram'); + expect(await dimensions[1].getVisibleText()).to.be('machine.os.raw: Descending'); + + expect((await lens.getMetricVisualizationData()).length).to.be.equal(6); + expect(await lens.getMetricVisualizationData()).to.eql([ + { + title: 'osx', + subtitle: 'Average machine.ram', + extraText: '', + value: '13.23B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + { + title: 'win 7', + subtitle: 'Average machine.ram', + extraText: '', + value: '13.19B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + { + title: 'win xp', + subtitle: 'Average machine.ram', + extraText: '', + value: '13.07B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + { + title: 'win 8', + subtitle: 'Average machine.ram', + extraText: '', + value: '13.03B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + { + title: 'ios', + subtitle: 'Average machine.ram', + extraText: '', + value: '13.01B', + color: 'rgba(245, 247, 250, 1)', + showingBar: false, + }, + { + title: undefined, + subtitle: undefined, + extraText: undefined, + value: undefined, + color: 'rgba(0, 0, 0, 0)', + showingBar: false, + }, + ]); + + dimensions[0].click(); + + await lens.openPalettePanel('lnsMetric'); + const colorStops = await lens.getPaletteColorStops(); + + expect(colorStops).to.eql([ + { stop: '0', color: 'rgba(0, 104, 55, 1)' }, + { stop: '10000', color: 'rgba(165, 0, 38, 1)' }, + { stop: '20000', color: undefined }, + ]); + }); }); } diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/table.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/table.ts index 09466bd7f1c70..c03773e3276b1 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/table.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/table.ts @@ -45,8 +45,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('should show the "Edit Visualization in Lens" menu item', async () => { - const button = await testSubjects.exists('visualizeEditInLensButton'); - expect(button).to.eql(true); + expect(await visualize.hasNavigateToLensButton()).to.eql(true); }); it('should convert aggregation with params', async () => { @@ -56,8 +55,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); @@ -77,8 +75,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); @@ -98,8 +95,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); @@ -121,8 +117,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); @@ -145,8 +140,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); @@ -168,8 +162,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('lnsDataTable'); expect(await lens.getLayerCount()).to.be(1); diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/xy.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/xy.ts index 161a3549e856c..fa6b603584daa 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/xy.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/xy.ts @@ -36,8 +36,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('should show the "Edit Visualization in Lens" menu item', async () => { - const button = await testSubjects.exists('visualizeEditInLensButton'); - expect(button).to.eql(true); + expect(await visualize.hasNavigateToLensButton()).to.eql(true); }); it('should hide the "Edit Visualization in Lens" menu item if dot size aggregation is defined', async () => { @@ -45,8 +44,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.selectAggregation('Max', 'metrics'); await visEditor.selectField('memory', 'metrics'); await visEditor.clickGo(isNewChartsLibraryEnabled); - const button = await testSubjects.exists('visualizeEditInLensButton'); - expect(button).to.eql(false); + expect(await visualize.hasNavigateToLensButton()).to.eql(false); }); it('should convert to Lens', async () => { @@ -57,8 +55,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visEditor.clickGo(isNewChartsLibraryEnabled); const expectedData = await visChart.getLegendEntriesXYCharts('xyVisChart'); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('xyVisChart'); const data = await lens.getCurrentChartDebugState('xyVisChart'); await retry.try(async () => { diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index.ts b/x-pack/test/functional/apps/ml/data_visualizer/index.ts index ab14b7f3c86c0..13ed76a002ca6 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index.ts @@ -33,6 +33,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { }); loadTestFile(require.resolve('./index_data_visualizer')); + loadTestFile(require.resolve('./index_data_visualizer_random_sampler')); loadTestFile(require.resolve('./index_data_visualizer_filters')); loadTestFile(require.resolve('./index_data_visualizer_grid_in_discover')); loadTestFile(require.resolve('./index_data_visualizer_grid_in_dashboard')); diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts new file mode 100644 index 0000000000000..7df4e9c18eee7 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { farequoteDataViewTestData, farequoteLuceneSearchTestData } from './index_test_data'; + +export default function ({ getPageObject, getService }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + const browser = getService('browser'); + async function goToSourceForIndexBasedDataVisualizer(sourceIndexOrSavedSearch: string) { + await ml.testExecution.logTestStep(`navigates to Data Visualizer page`); + await ml.navigation.navigateToDataVisualizer(); + + await ml.testExecution.logTestStep(`loads the saved search selection page`); + await ml.dataVisualizer.navigateToIndexPatternSelection(); + + await ml.testExecution.logTestStep(`loads the index data visualizer page`); + await ml.jobSourceSelection.selectSourceForIndexBasedDataVisualizer(sourceIndexOrSavedSearch); + } + describe('index based random sampler controls', function () { + this.tags(['ml']); + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/module_sample_logs'); + + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.createIndexPatternIfNeeded('ft_module_sample_logs', '@timestamp'); + await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded(); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.securityUI.loginAsMlPowerUser(); + // Start navigation from the base of the ML app. + await ml.navigation.navigateToMl(); + }); + + after(async () => { + await ml.testResources.deleteSavedSearches(); + await ml.testResources.deleteIndexPatternByTitle('ft_farequote'); + await ml.testResources.deleteIndexPatternByTitle('ft_module_sample_logs'); + await browser.removeLocalStorageItem('dataVisualizer.randomSamplerPreference'); + }); + + describe('with small data sets', function () { + it(`has random sampler 'on - automatic' by default`, async () => { + await goToSourceForIndexBasedDataVisualizer( + farequoteDataViewTestData.sourceIndexOrSavedSearch + ); + + await ml.dataVisualizerIndexBased.assertRandomSamplingOption( + 'dvRandomSamplerOptionOnAutomatic', + 100 + ); + }); + + it(`retains random sampler 'off' setting`, async () => { + await ml.dataVisualizerIndexBased.setRandomSamplingOption('dvRandomSamplerOptionOff'); + + await goToSourceForIndexBasedDataVisualizer( + farequoteLuceneSearchTestData.sourceIndexOrSavedSearch + ); + await ml.dataVisualizerIndexBased.assertRandomSamplingOption('dvRandomSamplerOptionOff'); + }); + + it(`retains random sampler 'on - manual' setting`, async () => { + await ml.dataVisualizerIndexBased.setRandomSamplingOption('dvRandomSamplerOptionOnManual'); + + await goToSourceForIndexBasedDataVisualizer('ft_module_sample_logs'); + await ml.dataVisualizerIndexBased.assertRandomSamplingOption( + 'dvRandomSamplerOptionOnManual', + 50 + ); + }); + }); + }); +} diff --git a/x-pack/test/functional/services/ml/data_visualizer_index_based.ts b/x-pack/test/functional/services/ml/data_visualizer_index_based.ts index 0e1860de4dab9..600790294a539 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_index_based.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_index_based.ts @@ -17,6 +17,7 @@ export function MachineLearningDataVisualizerIndexBasedProvider({ const PageObjects = getPageObjects(['discover']); const queryBar = getService('queryBar'); const filterBar = getService('filterBar'); + const browser = getService('browser'); return { async assertTimeRangeSelectorSectionExists() { @@ -231,5 +232,88 @@ export function MachineLearningDataVisualizerIndexBasedProvider({ } ); }, + + async assertRandomSamplingOptionsButtonExists() { + await testSubjects.existOrFail('dvRandomSamplerOptionsButton'); + }, + + async assertRandomSamplingOption( + expectedOption: + | 'dvRandomSamplerOptionOnAutomatic' + | 'dvRandomSamplerOptionOnManual' + | 'dvRandomSamplerOptionOff', + expectedProbability?: number + ) { + await retry.tryForTime(20000, async () => { + await browser.pressKeys(browser.keys.ESCAPE); + await testSubjects.clickWhenNotDisabled('dvRandomSamplerOptionsButton'); + await testSubjects.existOrFail('dvRandomSamplerOptionsPopover'); + + if (expectedOption === 'dvRandomSamplerOptionOff') { + await testSubjects.existOrFail('dvRandomSamplerOptionOff', { timeout: 1000 }); + await testSubjects.missingOrFail('dvRandomSamplerProbabilityRange', { timeout: 1000 }); + await testSubjects.missingOrFail('dvRandomSamplerAutomaticProbabilityMsg', { + timeout: 1000, + }); + } + + if (expectedOption === 'dvRandomSamplerOptionOnManual') { + await testSubjects.existOrFail('dvRandomSamplerOptionOnManual', { timeout: 1000 }); + await testSubjects.existOrFail('dvRandomSamplerProbabilityRange', { timeout: 1000 }); + if (expectedProbability !== undefined) { + const probability = await testSubjects.getAttribute( + 'dvRandomSamplerProbabilityRange', + 'value' + ); + expect(probability).to.eql( + `${expectedProbability}`, + `Expected probability to be ${expectedProbability}, got ${probability}` + ); + } + } + + if (expectedOption === 'dvRandomSamplerOptionOnAutomatic') { + await testSubjects.existOrFail('dvRandomSamplerOptionOnAutomatic', { timeout: 1000 }); + await testSubjects.existOrFail('dvRandomSamplerAutomaticProbabilityMsg', { + timeout: 1000, + }); + + if (expectedProbability !== undefined) { + const probabilityText = await testSubjects.getVisibleText( + 'dvRandomSamplerAutomaticProbabilityMsg' + ); + expect(probabilityText).to.contain( + `${expectedProbability}`, + `Expected probability text to contain ${expectedProbability}, got ${probabilityText}` + ); + } + } + }); + }, + + async setRandomSamplingOption( + option: + | 'dvRandomSamplerOptionOnAutomatic' + | 'dvRandomSamplerOptionOnManual' + | 'dvRandomSamplerOptionOff' + ) { + await retry.tryForTime(20000, async () => { + // escape popover + await browser.pressKeys(browser.keys.ESCAPE); + await this.assertRandomSamplingOptionsButtonExists(); + await testSubjects.clickWhenNotDisabled('dvRandomSamplerOptionsButton'); + await testSubjects.existOrFail('dvRandomSamplerOptionsPopover', { timeout: 1000 }); + + await testSubjects.clickWhenNotDisabled('dvRandomSamplerOptionsSelect'); + + await testSubjects.existOrFail('dvRandomSamplerOptionOff', { timeout: 1000 }); + await testSubjects.existOrFail('dvRandomSamplerOptionOnManual', { timeout: 1000 }); + await testSubjects.existOrFail('dvRandomSamplerOptionOnAutomatic', { timeout: 1000 }); + + await testSubjects.click(option); + + await this.assertRandomSamplingOption(option); + }); + }, }; } diff --git a/x-pack/test/functional/services/transform/discover.ts b/x-pack/test/functional/services/transform/discover.ts index d96ab079043a0..944e65b73f6e2 100644 --- a/x-pack/test/functional/services/transform/discover.ts +++ b/x-pack/test/functional/services/transform/discover.ts @@ -15,9 +15,11 @@ export function TransformDiscoverProvider({ getService }: FtrProviderContext) { return { async assertDiscoverQueryHits(expectedDiscoverQueryHits: string) { - await testSubjects.existOrFail('discoverQueryHits'); + await testSubjects.existOrFail('unifiedHistogramQueryHits'); - const actualDiscoverQueryHits = await testSubjects.getVisibleText('discoverQueryHits'); + const actualDiscoverQueryHits = await testSubjects.getVisibleText( + 'unifiedHistogramQueryHits' + ); expect(actualDiscoverQueryHits).to.eql( expectedDiscoverQueryHits, @@ -59,7 +61,7 @@ export function TransformDiscoverProvider({ getService }: FtrProviderContext) { expect(actualApplyButtonText).to.be('Apply'); await applyButton.click(); - await testSubjects.existOrFail('discoverQueryHits'); + await testSubjects.existOrFail('unifiedHistogramQueryHits'); }, }; } diff --git a/x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts b/x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts index 472af7376d02e..7f2b386c7c736 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/alert_details_page.ts @@ -5,7 +5,6 @@ * 2.0. */ -import uuid from 'uuid'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { @@ -28,10 +27,12 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); }); - it('should show 404 page when the feature flag is disabled', async () => { - await observability.alerts.common.navigateToAlertDetails(uuid.v4()); + it('should show 404 page when the feature flag is disabled but the alert exists', async () => { + await observability.alerts.common.navigateToAlertDetails( + '4c87bd11-ff31-4a05-8a04-833e2da94858' + ); await retry.waitFor( - 'Alerts page to be visible', + 'The 404 - Not found page to be visible', async () => await testSubjects.exists('pageNotFound') ); }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index bb0bd27ce85d9..9d88842f2b0fd 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -219,8 +219,8 @@ export function bulkCreateTestSuiteFactory(context: FtrProviderContext) { }); after(async () => { + await testDataLoader.deleteAllSavedObjectsFromKibanaIndex(); await testDataLoader.deleteFtrSpaces(); - await testDataLoader.deleteFtrSavedObjectsData(); }); const attrs = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts index c9cb3b9739eee..15a51c3db3364 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts @@ -117,8 +117,8 @@ export function bulkGetTestSuiteFactory(context: FtrProviderContext) { }); after(async () => { - await testDataLoader.deleteFtrSpaces(); await testDataLoader.deleteFtrSavedObjectsData(); + await testDataLoader.deleteFtrSpaces(); }); for (const test of tests) { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts index 80053108b46fa..4643b91303be0 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts @@ -16,8 +16,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const endpointTestResources = getService('endpointTestResources'); const policyTestResources = getService('policyTestResources'); - // FLAKY: https://github.com/elastic/kibana/issues/114309 - describe.skip('When on the Trusted Apps list', function () { + describe('When on the Trusted Apps list', function () { let indexedData: IndexedHostsAndAlertsResponse; before(async () => { const endpointPackage = await policyTestResources.getEndpointPackage();